<!DOCTYPE html><meta charset=utf-8>
<title>HTML Editing APIs</title>
<link href=https://www.whatwg.org/style/specification rel=stylesheet>
<style>
pre, code, xmp { font-family:monospace, sans-serif; }
h2 code, h3 code, h3 code,
h2 :link, h3 :link, h3 :link,
h2 :visited, h3 :visited, h3 :visited
{ font:inherit; color:inherit; font-style:italic; }
@media print {
  :not([data-anolis-spec]) > [data-anolis-spec]::after {
    content: "[" attr(data-anolis-spec) "]";
    font-size: 0.6em;
    vertical-align: super;
    text-transform: uppercase;
  }
}
xmp {
  font-size: inherit;
  font-variant: normal;
  margin-left: 2em;
  white-space: pre-wrap;
}
div.note > p:first-child::before,
li.note > p:first-child::before { content: 'Note: ' }
.note var { font-style: normal }
li.note { display: block }
.XXX > :last-child { margin-bottom: 0 }
.XXX li {
  margin-top: 0;
  margin-bottom: 0;
}
dd .XXX p { margin: 1em 0 }
ol li { margin: 1em 0 }
li li, li li > p { margin: 0 }
li p + * > li:first-child { margin-top: -1em }
li li > p + * > li:first-child { margin-top: 0 }
table { margin: 1em 0 }
.toc, .toc li { list-style-type: disc }
.toc li li { list-style-type: circle }
/* Overwrite the underline so it's orange instead of blue, thus looks less
 * silly */
a code { text-decoration: underline }
/* Comments stuff */
.comments { display: none }
.comments-wrapper {
  font-size: small;
  color: #333;
}
.comments-wrapper > button {
  float: right;
  margin-left: 0.3em;
}
.comments-expanded {
  position: absolute;
  z-index: 1;
  right: 0;
  width: 50%;
  background: white;
  border: 1px solid gray;
  padding: 0.5em;
  margin-top: 2em;
}
.comments-expanded :first-child { margin-top: 0 }
.comments-expanded :last-child { margin-bottom: 0 }
</style>
<body class=draft>
<div class=head id=head>
<p><a href=https://www.w3.org/><img alt=W3C height=48 src=https://www.w3.org/Icons/w3c_home width=72></a></p>
<h1>HTML Editing APIs</h1>
<h2 class="no-num no-toc" id=work-in-progress-&mdash;-last-update-13-february-2014>Work in Progress &mdash; Last Update 13 February 2014</h2>
<dl>
 <dt>Editor
 <dd>Aryeh Gregor &lt;<a href=mailto:ayg@aryeh.name>ayg@aryeh.name</a>&gt;

 <dt>Latest version
 <dd><a href=https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html>W3C Mercurial</a>

 <dt>Version history
 <dd><a href=https://dvcs.w3.org/hg/editing>W3C Mercurial</a>
 <dd><a href=https://github.com/ayg/editing>github mirror</a>

 <dt>Issue tracker
 <dd><a href="https://www.w3.org/Bugs/Public/buglist.cgi?component=HTML+Editing+APIs&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED">All open issues</a>
 <dd><a href="https://www.w3.org/Bugs/Public/enter_bug.cgi?product=WebAppsWG&amp;component=HTML+Editing+APIs">File an issue</a>

 <dt>Mailing list
 <dd><a href="mailto:public-webapps@w3.org?cc=ayg@aryeh.name&amp;subject=%5Bediting%5D%20">public-webapps</a> (<a href=https://lists.w3.org/Archives/Public/public-webapps/>archive</a>;
 include "[editing]" in the subject)

 <dt>IRC chat
 <dd><a href=irc://irc.freenode.net/whatwg>#whatwg on freenode</a>
</dl>
</div>


<h2 class=no-num id=status-of-this-document>Status of this Document</h2>

<p>This document is a preliminary draft of a specification for HTML editing
APIs, mainly defining <a href=#concept-selection title=concept-selection>selections</a>, <code><a href=#execcommand()>execCommand()</a></code> and related
functionality.  It replaces a couple of old sections of the <a href=https://www.whatwg.org/html>HTML</a> specification, and the <a href=#concept-selection title=concept-selection>selection</a>
part of the old DOM Range specification.  Issues that don't necessarily need
discussion should preferably be <a href="https://www.w3.org/Bugs/Public/enter_bug.cgi?product=WebAppsWG&amp;component=HTML+Editing+APIs">filed
in the issue tracker</a>.  Feedback that needs discussion should preferably be
sent to <a href="mailto:public-webapps@w3.org?cc=ayg@aryeh.name&amp;subject=%5Bediting%5D%20">the
public-webapps list</a>, with the string "[editing]" somewhere in the subject,
CC'd to <a href=mailto:ayg@aryeh.name>ayg@aryeh.name</a> to make sure I see it.
I will handle all feedback I'm aware of, either addressing it immediately or
filing a bug if it needs longer-term consideration and is not already filed.

<p>Copyright &copy; 2014 the Contributors to the HTML Editing APIs Specification,
published by the <a href=https://www.w3.org/community/editing/>W3C Editing
APIs Community Group</a> under the <a href=https://www.w3.org/community/about/agreements/cla/>W3C Community
Contributor License Agreement (CLA)</a>. A human-readable <a href=https://www.w3.org/community/about/agreements/cla-deed/>summary</a> is
available.

<p>This specification, along with the accompanying JavaScript implementation
and tests, may also be used under the terms of the <a href=https://creativecommons.org/publicdomain/zero/1.0/>CC0 1.0 Universal
License</a>.  Thus anyone may reuse, modify, and redistribute them without
restriction.

<p>This specification was published by the <a href=https://www.w3.org/community/editing/>W3C Editing APIs Community Group</a>.
It is not a W3C Standard nor is it on the W3C Standards Track. Please note that
under the <a href=https://www.w3.org/community/about/agreements/cla/>W3C
Community Contributor License Agreement (CLA)</a> there is a limited opt-out
and other conditions apply. Learn more about <a href=https://www.w3.org/community/>W3C Community and Business Groups</a>.


<h2 class=no-num id=table-of-contents>Table of contents</h2>

<!--begin-toc-->
<ol class=toc>
 <li><a class=no-num href=#status-of-this-document>Status of this Document</a></li>
 <li><a class=no-num href=#table-of-contents>Table of contents</a></li>
 <li><a href=#introduction>Introduction</a></li>
 <li><a href=#tests>Tests</a>
  <ol>
   <li><a href=#general-remarks>General remarks</a></li>
   <li><a href=#development-tests>Command development tests</a></li>
   <li><a href=#conformance-tests>Command conformance tests</a></ol></li>
 <li><a href=#issues>Issues</a></li>
 <li><a href=#selections>Selections</a></li>
 <li><a href=#commands>Commands</a>
  <ol>
   <li><a href=#properties-of-commands>Properties of commands</a></li>
   <li><a href=#supported-commands>Supported commands</a></li>
   <li><a href=#enabled-commands>Enabled commands</a></ol></li>
 <li><a href=#methods-to-query-and-execute-commands>Methods to query and execute commands</a></li>
 <li><a href=#common-definitions>Common definitions</a></li>
 <li><a href=#common-algorithms>Common algorithms</a>
  <ol>
   <li><a href=#assorted-common-algorithms>Assorted common algorithms</a></li>
   <li><a href=#wrapping-a-list-of-nodes>Wrapping a list of nodes</a></li>
   <li><a href=#allowed-children>Allowed children</a></ol></li>
 <li><a href=#inline-formatting-commands>Inline formatting commands</a>
  <ol>
   <li><a href=#inline-formatting-command-definitions>Inline formatting command definitions</a></li>
   <li><a href=#assorted-inline-formatting-command-algorithms>Assorted inline formatting command algorithms</a></li>
   <li><a href="#clearing-an-element's-value">Clearing an element's value</a></li>
   <li><a href=#pushing-down-values>Pushing down values</a></li>
   <li><a href=#forcing-the-value-of-a-node>Forcing the value of a node</a></li>
   <li><a href="#setting-the-selection's-value">Setting the selection's value</a></li>
   <li><a href=#the-backcolor-command>The <code title="">backColor</code> command</a></li>
   <li><a href=#the-bold-command>The <code title="">bold</code> command</a></li>
   <li><a href=#the-createlink-command>The <code title="">createLink</code> command</a></li>
   <li><a href=#the-fontname-command>The <code title="">fontName</code> command</a></li>
   <li><a href=#the-fontsize-command>The <code title="">fontSize</code> command</a></li>
   <li><a href=#the-forecolor-command>The <code title="">foreColor</code> command</a></li>
   <li><a href=#the-hilitecolor-command>The <code title="">hiliteColor</code> command</a></li>
   <li><a href=#the-italic-command>The <code title="">italic</code> command</a></li>
   <li><a href=#the-removeformat-command>The <code title="">removeFormat</code> command</a></li>
   <li><a href=#the-strikethrough-command>The <code title="">strikethrough</code> command</a></li>
   <li><a href=#the-subscript-command>The <code title="">subscript</code> command</a></li>
   <li><a href=#the-superscript-command>The <code title="">superscript</code> command</a></li>
   <li><a href=#the-underline-command>The <code title="">underline</code> command</a></li>
   <li><a href=#the-unlink-command>The <code title="">unlink</code> command</a></ol></li>
 <li><a href=#block-formatting-commands>Block formatting commands</a>
  <ol>
   <li><a href=#block-formatting-command-definitions>Block formatting command definitions</a></li>
   <li><a href=#assorted-block-formatting-command-algorithms>Assorted block formatting command algorithms</a></li>
   <li><a href=#block-extending-a-range>Block-extending a range</a></li>
   <li><a href=#recording-and-restoring-overrides>Recording and restoring overrides</a></li>
   <li><a href=#deleting-the-selection>Deleting the selection</a></li>
   <li><a href="#splitting-a-node-list's-parent">Splitting a node list's parent</a></li>
   <li><a href=#canonical-space-sequences>Canonical space sequences</a></li>
   <li><a href=#indenting-and-outdenting>Indenting and outdenting</a></li>
   <li><a href=#toggling-lists>Toggling lists</a></li>
   <li><a href=#justifying-the-selection>Justifying the selection</a></li>
   <li><a href=#automatic-linking>Automatic linking</a></li>
   <li><a href=#the-delete-command>The <code title="">delete</code> command</a></li>
   <li><a href=#the-formatblock-command>The <code title="">formatBlock</code> command</a></li>
   <li><a href=#the-forwarddelete-command>The <code title="">forwardDelete</code> command</a></li>
   <li><a href=#the-indent-command>The <code title="">indent</code> command</a></li>
   <li><a href=#the-inserthorizontalrule-command>The <code title="">insertHorizontalRule</code> command</a></li>
   <li><a href=#the-inserthtml-command>The <code title="">insertHTML</code> command</a></li>
   <li><a href=#the-insertimage-command>The <code title="">insertImage</code> command</a></li>
   <li><a href=#the-insertlinebreak-command>The <code title="">insertLineBreak</code> command</a></li>
   <li><a href=#the-insertorderedlist-command>The <code title="">insertOrderedList</code> command</a></li>
   <li><a href=#the-insertparagraph-command>The <code title="">insertParagraph</code> command</a></li>
   <li><a href=#the-inserttext-command>The <code title="">insertText</code> command</a></li>
   <li><a href=#the-insertunorderedlist-command>The <code title="">insertUnorderedList</code> command</a></li>
   <li><a href=#the-justifycenter-command>The <code title="">justifyCenter</code> command</a></li>
   <li><a href=#the-justifyfull-command>The <code title="">justifyFull</code> command</a></li>
   <li><a href=#the-justifyleft-command>The <code title="">justifyLeft</code> command</a></li>
   <li><a href=#the-justifyright-command>The <code title="">justifyRight</code> command</a></li>
   <li><a href=#the-outdent-command>The <code title="">outdent</code> command</a></ol></li>
 <li><a href=#miscellaneous-commands>Miscellaneous commands</a>
  <ol>
   <li><a href=#the-copy-command>The <code title="">copy</code> command</a></li>
   <li><a href=#the-cut-command>The <code title="">cut</code> command</a></li>
   <li><a href=#the-defaultparagraphseparator-command>The <code title="">defaultParagraphSeparator</code> command</a></li>
   <li><a href=#the-paste-command>The <code title="">paste</code> command</a></li>
   <li><a href=#the-redo-command>The <code title="">redo</code> command</a></li>
   <li><a href=#the-selectall-command>The <code title="">selectAll</code> command</a></li>
   <li><a href=#the-stylewithcss-command>The <code title="">styleWithCSS</code> command</a></li>
   <li><a href=#the-undo-command>The <code title="">undo</code> command</a></li>
   <li><a href=#the-usecss-command>The <code title="">useCSS</code> command</a></ol></li>
 <li><a href=#additional-requirements>Additional requirements</a></li>
 <li><a class=no-num href=#acknowledgements>Acknowledgements</a></ol>
<!--end-toc-->

<h2 id=introduction>Introduction</h2>

<p class=comments>
<a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=16206">Bug 16206</a>.

<p>A piece of software that claims to implement this specification must follow
every <dfn id=normative>normative</dfn> requirement in it.  Every requirement in this
specification is <a href=#normative>normative</a> unless stated otherwise.

<p class=comments>These are comments.  All comments other than this one are
non-<a href=#normative>normative</a>.

<p class=note>This is a note.  All notes other than this one are
non-<a href=#normative>normative</a>.

<p class=XXX>This is an open issue.  All issues other than this one are
non-<a href=#normative>normative</a>.

<p>The remainder of this section is not <a href=#normative>normative</a>, and nor is any
preceding section.

<p>This specification defines commands to edit HTML documents programmatically.
The APIs specified here were originally introduced in Microsoft's Internet
Explorer, but have subsequently been copied by other browsers in a haphazard
and imprecise fashion.  Although the behavior specified here does not exactly
match any browser at the time of writing, it can serve as a target to converge
to in the future.

<p>Where the reasoning behind the specification is of interest, such as when
major preexisting rendering engines are known not to match it, the reasoning is
available by clicking the "comments" button on the right (requires JavaScript).
If you have questions about why the specification says something, check the
comments first.  They're sometimes longer than the specification text itself,
and commonly record what the major browsers do and other essential information.

<p>The principles I've used for writing this specification so far are:

<ul>
  <li>If all browsers that implement a particular feature agree on some detail
  of how it works, match them unless there's very good reason not to.  When
  it's not clear what behavior is best, try to follow the implementations with
  the most market share.  But if one browser's behavior is clearly better than
  the others', go with the better behavior.

  <li>If a command is issued to format some text in a particular way, we will
  format the text that way no matter what.  If the user clicks the "bold"
  button, they don't care that the text didn't become bold because of an
  external CSS rule or for any other reason, they only care that it didn't
  work.  The only exception (beyond where it's simply impossible, like
  propagated text-decorations we can't remove) is that we don't try to override
  !important rules from external stylesheets, although we also don't go out of
  our way to respect them.

  <li>When we're given a presentational command like "bold", don't modify
  anything other than presentational markup related to that command.  If an
  element has non-presentational attributes like id or class, don't split it up
  or remove it or anything.  At most convert it to a span, if it's some type of
  presentational element.  ("Presentational" here really means "browsers
  produce it in response to execCommand() so we need to treat it as
  presentational", so it includes things like <code class=external data-anolis-spec=html title="the strong element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-strong-element>strong</a></code> and <code class=external data-anolis-spec=html title="the em element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-em-element>em</a></code>.)  Of
  course, in some cases we have to remove elements, like when merging two
  blocks.

  <li>Don't interfere with more markup than necessary.  If the user modifies
  only a small run of text, don't go around simplifying ancestors or siblings
  or whatever unless it's necessary to produce simpler markup in the place that
  was actually modified.

  <li>But if we are already changing around something's style, convert existing
  styles to the preferred format.  For instance, we use <code title="">&lt;b&gt;</code> for bold
  (if the CSS styling flag is false), and convert <code title="">&lt;strong&gt;</code> and
  <code title="">&lt;span style="font-weight: bold"&gt;</code> if we happen to be modifying
  that node anyway.

  <li>Try not to make the document less conforming than it originally was.  If
  we happen to make it more conforming, good, although we don't have to go out
  of our way to do that.  In some cases we do make the document less
  conforming, generally because there's some clear use-case that requires it or
  because it matches existing browsers behavior.  (For instance, see the
  styleWithCSS = false mode, and the fact that insertImage doesn't add an
  alt attribute, etc.)

  <li>Keep the markup as concise as possible.  (I've received feedback that
  this is very important to authors.)  Ideally, the markup should look as
  simple and neat as what a human would have produced by hand-editing.  We do
  complicated manipulation to pull styles down from ancestors rather than
  having to use inline CSS, and make sure to tidy up any styles on elements
  that we happen to be modifying anyway.  Previous principles take precedence
  over this one, however.
</ul>


<h2 id=tests>Tests</h2>

<p><i title="">This section is not <a href=#normative>normative</a>.</i>

<h3 id=general-remarks>General remarks</h3>


<p>There are two groups of tests currently associated with this document:
selection tests, and command tests.  These tests are a
non-<a href=#normative>normative</a> part of this specification.  The command tests are
available in two formats, development tests and conformance tests.  This has a
lot to do with the history of how the specification was developed: selection
was originally part of the defunct <a href=http://html5.org/specs/dom-range.html>DOM Range</a> spec, while the
command parts were developed on their own.  The selection things have been
merged into the command spec, but neither the spec text nor the tests have been
fully unified at the time of this writing.

<p>Thus the selection tests live in their own directory, <a href=selecttest/>selecttest/</a>.  They use the standard <a href=https://github.com/w3c/testharness.js/blob/master/testharness.js>testharness.js</a>
framework developed by James Graham.  They're entirely self-contained, sharing
nothing with the command tests (except invoking the testharness.js library).
At the time of this writing, they're not nearly as comprehensive as the command
tests, although they do test some functionality comprehensively.

<p>On the other hand, the command-related part of this specification is
developed in tandem with a more or less complete <a href=implementation.js>JavaScript implementation</a>.  The implementation is
used for creating tests, of two different types: development tests and
conformance tests.  The two types of test share most of the same code, starting
with the multi-thousand-line implementation itself.  The actual tests run are
largely the same in either case, but the way they're run is very different.

<p>The development tests were the original ones, and were designed to assist in
writing the specification from scratch.  Given an input, they print out the
spec's and browser's output to allow manual inspection.  They can store the
spec's output and will raise an alert if it changed since the last run, as a
form of regression testing, but they don't print out counts of passed/failed
tests.  They are not designed to run exactly the same across browsers and are
tolerant of minor variations.  Development tests are likely not very useful for
anyone other than the spec's editor.

<p>Conformance tests were added later.  They run the same tests as the
development tests, but in an entirely non-interactive format, using the <a href=https://github.com/w3c/testharness.js/blob/master/testharness.js>testharness.js</a>
framework like the selection tests.  They always run the same set of tests,
don't vary behavior between browsers (hopefully), and are unforgiving of any
deviation.  However, they're significantly more cumbersome to set up and use,
so they're less useful for developing the specification itself.

<p>There's a suite of predefined tests for each command (~30&ndash;300 at the
time of this writing).  These are the only tests run for the conformance tests,
and in the regression tests they can be run by clicking the "Run tests" button.
For the regression tests, you can also enter your own tests manually in the box
provided.  In any event, the test input is a snippet of HTML, which must have a
selection marked in it.  There are three ways to mark a selection's start or
end:

<ol>
  <li>Square brackets mark a selection inside a text node, like
  <code title="">&lt;b&gt;foo[bar]baz&lt;/b&gt;</code> for a selection whose start and end nodes are in
  the text node <code title="">foobarbaz</code>, with start offset 3 and end offset 6.  Do
  not use square brackets where there's no text node: <code title="">&lt;b&gt;[]&lt;/b&gt;</code> is
  bad, <code title="">&lt;b&gt;{}&lt;/b&gt;</code> is correct.

  <li>Curly braces mark a selection inside an element, like
  <code title="">&lt;b&gt;{foobarbaz&lt;/b&gt;}</code> for a selection whose start node is the element
  <code title="">&lt;b&gt;</code>, whose start offset is 0, whose end node is the root of the
  editable region, and whose end offset is 1.  Do not use curly braces in the
  middle of a text node: <code title="">foo{bar}baz</code> is bad, <code title="">foo[bar]baz</code> is correct.

  <li>The <code title="">data-start</code> and <code title="">data-end</code>
  attributes mark a selection inside an element if a curly brace can't be put
  there in text/html.  For instance,
  <code title="">&lt;table&gt;&lt;tr&gt;{&lt;td&gt;foo&lt;/td&gt;}&lt;/tr&gt;&lt;/table&gt;</code> doesn't work because when the
  fragment is parsed, the curly braces end up outside the table.  Instead, you
  have to do <code title="">&lt;table&gt;&lt;tr data-start=0 data-end=1&gt;&lt;td&gt;foo&lt;/table&gt;</code>.
</ol>

<p>Every input must have exactly one start marker and one end marker, which
will be removed from the DOM before the test is run.  You can mix and match
marker types, e.g., <code title="">[foo}</code>.

<p>There is one special test type that behaves differently, "multitest".  This
allows running several tests in succession, which is needed at least for
testing the effect of commands' <a href=#state-override>state override</a> or <a href=#value-override>value
override</a>.  The syntax is JSON, and looks like

<pre>[<var title="">HTML input</var>,
  [<var title="">command name 1</var>, <var title="">command value 1</var>],
  [<var title="">command name 2</var>, <var title="">command value 2</var>],
  . . .]</pre>

<p>where all the variables are properly-quoted JSON strings.  <code title="">queryCommand*()</code> are not run for multitests.

<p>In all cases, prefixing the test string (or the first string in the test
array, for arrays) with "!" has a special effect.  The "!" will be stripped,
and the test will be added to an array of bad tests.  These tests will be
omitted from the <a href=#conformance-tests>conformance tests</a>.  This is
used to mark tests where the reference implementation is known to currently
give bad results, either because of a bug in the reference implementation or a
bug in the spec.  Bad tests will still be run as <a href=#development-tests>development tests</a>.

<p>Commands that are expected to vary significantly based on the value of the
<a href=#css-styling-flag>CSS styling flag</a> are run twice.  The first time runs
<code title="">execCommand("styleWithCSS", false, "false")</code> before every
command, and the second runs <code title="">execCommand("styleWithCSS", false,
"true")</code> before every command.  All other commands other than multitests
run <code title="">execCommand("styleWithCSS", false, "false")</code> before every
command.  The extra tests are not run as regression tests, in IE or Opera,
because they don't implement <a href=#the-stylewithcss-command>the <code title="">styleWithCSS</code>
command</a> (but of course the conformance tests always all run).

<p>The implementation is also used for an actual <a href=editor.html>rich-text
editor</a>, but it's currently more of a toy than anything.  Significant
functionality is probably broken, especially outside of Gecko/WebKit.  I might
spend some more time getting it to work right, but it's certainly not going to
be very useful on real-world sites, since there's no way any of this stuff will
work in IE8.


<h3 id=development-tests>Command development tests</h3>


<p>The development tests are mostly useful for developing the spec itself, not
for use by authors or browser implementers.  They consist of a suite of fully
automated tests plus a few separate suites of manual tests.  The tests are:

<ul>
  <li><a href=autoimplementation.html>autoimplementation.html</a>: Fully
  automated tests for pretty much all commands.

  <li><a href=deletetest.html>deletetest.html</a>: Manual tests for <a href=#the-delete-command>the
  <code title="">delete</code> command</a>.

  <li><a href=forwarddeletetest.html>forwarddeletetest.html</a>: Manual tests
  for <a href=#the-forwarddelete-command>the <code title="">forwardDelete</code> command</a>.

  <li><a href=insertlinebreaktest.html>insertlinebreaktest.html</a>: Manual
  tests for <a href=#the-insertlinebreak-command>the <code title="">insertLineBreak</code> command</a>.

  <li><a href=insertparagraphtest.html>insertparagraphtest.html</a>: Manual
  tests for <a href=#the-insertparagraph-command>the <code title="">insertParagraph</code> command</a>.

  <li><a href=inserttexttest.html>inserttexttest.html</a>: Manual tests for
  <a href=#the-inserttext-command>the <code title="">insertText</code> command</a>, with <var title="">value</var>
  "a".

  <li><a href=inserttext2test.html>inserttext2test.html</a>: Manual tests for
  <a href=#the-inserttext-command>the <code title="">insertText</code> command</a>, with <var title="">value</var>
  " ".
</ul>

<p>The automated tests run the JavaScript implementation of the specification
on a particular input, then run the browser's implementation on the same input
for comparison.  The results of running automated tests are placed in a table,
with rows marked as passing or failing based on whether the browser output is
"close enough" to the spec output.  Since the tests are designed for debugging
the spec rather than actually testing conformance, minor variations are allowed
to avoid having browsers fail many tests for uninteresting reasons.  Passes and
fails are based only on <code><a href=#execcommand()>execCommand()</a></code> output, not <code title="">queryCommand*()</code>: the latter is sanity-checked, and colored green
or red if it's known to be right or wrong on general principle, but spec and
browser output are not compared.

<p>The tests will optionally store the specification's result for each test in
<code title="">localStorage</code>, and will raise an alert for any new test (no
stored output), any test whose spec output is different from the last run, and
any test whose spec output is otherwise clearly bad (e.g., producing a
non-serializable DOM).  This is mostly useful for debugging and
regression-testing the spec itself, and is probably not interesting to anyone
other than me.

<p>When a test runs, first the code sets up a contenteditable div with the
given contents and sets the selection as requested.  Then it runs
<code><a href=#querycommandindeterm()>queryCommandIndeterm()</a></code>, <code><a href=#querycommandstate()>queryCommandState()</a></code>, and
<code><a href=#querycommandvalue()>queryCommandValue()</a></code>, and their values are noted.  Then it runs
<code><a href=#execcommand()>execCommand()</a></code>.  Finally, it runs
<code><a href=#querycommandindeterm()>queryCommandIndeterm()</a></code>, <code><a href=#querycommandstate()>queryCommandState()</a></code>, and
<code><a href=#querycommandvalue()>queryCommandValue()</a></code> again.  Then it adds the output to the table.

<p>The manual tests are much like the automated tests, with some key
differences.  They only test one command each, with one input value (if
applicable).  When a test is run, everything proceeds as in the automated case,
but instead of running <code><a href=#execcommand()>execCommand()</a></code> for the browser tests, the
user is asked to hit the appropriate key (backspace, delete, enter, etc.).
Thus when running the tests for the first time, the user has to hit a key
repeatedly, perhaps a few hundred times.  The browser's result is then cached
in <code title="">localStorage</code> so no manual intervention is required on
subsequent runs except for newly-added tests, but the cached entries can be
cleared if necessary.

<p>The development tests have been tested and largely work in the latest
versions (at the time of this writing) of IE, Firefox, Chrome, and Opera.
Since the implementation of the spec is in JavaScript, it's vulnerable to bugs
in browsers' JavaScript implementations.  I work around or warn about some of
these, but not all.  The most correct results will probably be in Firefox or
Chrome: both IE and Opera have serious known bugs that corrupt spec output for
many tests.  The tests are still useful for reviewing the browser output, but
spec output in those browsers should be sanity-checked and compared against
another browser's spec output in case of doubt.


<h3 id=conformance-tests>Command conformance tests</h3>


<p>The conformance tests operate more like one would expect from tests.  Once
generated, they consist of a single page, <a href=conformancetest/runtest.html>conformancetest/runtest.html</a>, which runs
all the tests and prints out a table of passes and fails.  Like many other
recent web standards suites, they use the <a href=https://github.com/w3c/testharness.js/blob/master/testharness.js>testharness.js</a>
framework, and browser implementers should be able to make them part of their
automated regression test frameworks.

<p>For manual inspection, a version of the conformance tests is also available
that runs only some of the tests at once: <a href=conformancetest/splitruntest.html>conformancetest/splitruntest.html</a>.
This runs only one group of tests at a time, which takes only a few seconds
instead of a minute or more.  This makes debugging particular tests much
faster.  In all other respects, it should behave identically to runtest.html.

<p>Unlike the development tests, the conformance tests don't run the JavaScript
implementation as part of the test.  Instead, the tests' expected values are
generated by a separate page, <a href=conformancetest/gentest.html>conformancetest/gentest.html</a>.  That page
will output the expected values for all tests in a format to be copied to <a href=conformancetest/data.js>conformancetest/data.js</a>, where it will be used
by runtest.html.

<p>This separation has a few benefits.  First of all, it means the conformance
tests take a long time to generate, but run <em>much</em> faster than the
development tests: on the order of one minute instead of five or more.
(Browser implementations of <code title="">execCommand()</code> are currently much faster
than the spec's JS reference implementation, it seems.)  Second of all, it
means that all browsers are running against the same expected results.  Third
of all, the fact that all expected results are saved in a file allows much more
systematic regression testing of the spec and the reference implementation.
Changes in expected results will be recorded in the spec's version history and
can be matched up to changes in the reference implementation or the spec,
instead of being stored transiently in the spec editor's <code title="">localStorage</code>
and then lost.

<p>There are a couple of disadvantages as well.  For one thing, new tests can't
easily be added live, so the conformance tests aren't useful for experimenting
with how implementations work.  For another thing, the tests' expected results
can only be generated all at once (not per-command), which takes minutes.  A
third issue is that they provide no useful feedback at all about user actions
such as hitting Enter: they tell you what <a href=#the-insertparagraph-command>the <code title="">insertParagraph</code> command</a> does in the browser, but not
whether it matches up to any user action.  Commands like <a href=#the-inserttext-command>the <code title="">insertText</code> command</a> just fail all tests in most browsers.
Thus they don't replace the manual development tests at all.  (Manual
conformance tests will eventually be added.)

<p>As might be expected, browsers don't generate exactly the same expected
results from the tests.  Clearly incorrect expected results (like a DOM that
doesn't round-trip through text/html) are automatically rejected, with a
printed warning, but some discrepancies remain.  At the time of this writing,
Firefox 8.0a2 and Chrome 15 dev generate identical results, except that Firefox
omits one test (due to <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=578141">incorrect
serialization of <code title="">&lt;xmp&gt;</code></a>) and Chrome gets one test wrong (due to a
<a href="https://bugs.webkit.org/show_bug.cgi?id=67424">style resolution
bug</a>).  Thus I generate the tests right now in Firefox, since all its
generated tests are at least correct.  IE9 and Opera 11.50 don't yet generate
or run the tests usefully at all in this initial version, but this will be
remedied soon.

<p>Event firing is currently tested in a totally separate file,
<a href=conformancetest/event.html>event.html</a>.  In the long term, this will
probably be merged into runtest.html so that it's tested more thoroughly.



<h2 id=issues>Issues</h2>

<p><i title="">This section is not <a href=#normative>normative</a>.</i>

<p>This specification is mostly feature-complete.  It's more or less fully
implemented in JavaScript, and has been tested on a fairly significant amount
of artificial input.  It has not been tested on real-world sites that use
execCommand(), and has not been thoroughly reviewed by anyone other than me.
It should be considered mostly stable and awaiting implementater review and
feedback.

<p>Significant known issues that I need feedback on, or otherwise am not
planning to fix just yet:

<ul>
  <li>Need to make CSS terminology more precise, about setting/unsetting CSS
  properties.  The intent is to modify the style attribute, CSSOM-style.
  Suggestions appreciated on how I should spec this.

  <li>I use <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> instead of computed or used or anything like that, just
  because that's what my test implementation uses (via getComputedStyle).  This
  is not necessarily the best actual choice: if it should be something else,
  please tell me.

  <li><p>I haven't paid much attention to performance.  The algorithms here
  aren't performance-critical in most cases, but I might have accidentally
  included some algorithms that are too slow anyway on large pages.  Generally
  I haven't worried about throwing nodes away and recreating them multiple
  times or things like that, as long as it produces the correct result.

  <p>If it would be useful to implementers for me to spend time and spec
  complexity on avoiding some of the masses of useless operations that are
  currently required, please say so.  All intermediate DOM states are
  black-box detectable via mutation events or whatever their replacement will
  be, so implementers theoretically can't optimize most of this stuff too much
  themselves, but in practice I doubt anyone will rely on the intermediate DOM
  states much.

  <li><code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>s are a nightmare.  I have tons of hacks all over the place which
  are totally wrong, mostly to account for the fact that sometimes <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>s do
  nothing and we need to treat that case magically.  I don't know what a good
  way is to fix this.  At this point I've mostly gotten the evil concentrated
  in the definitions "collapsed line break", "extraneous line break", and
  "collapsed block prop", but there's lots of other special-case handling
  scattered about.  Feedback appreciated.  How do browsers handle this?

  <li>The CSS styling flag is an issue.  Currently authors are forced to turn
  it entirely on or entirely off.  If it's on, it produces stuff like <code title="">&lt;span style=font-weight:bold&gt;</code> instead of <code title="">&lt;b&gt;</code>, while if it's off, it produces stuff like <code title="">&lt;font color=red&gt;</code> instead of <code title="">&lt;span
  style=color:red&gt;</code>.  The issue is that authors might want a mix, like
  making the markup as concise as possible while still conforming, and they
  can't do that.  Changing the flag on a per-command basis doesn't help because
  of things like the "restore the values" algorithm, which might create several
  different types of style at once and has to use the same styling flag for all
  of them.  This was discussed back in March in <a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-March/030714.html>this
  thread</a>, along with a number of other things, but at that time I hadn't
  written commands that change multiple styles at once, so it seemed feasible
  to ask authors to switch styleWithCSS on or off on a per-command basis.

  <li>I haven't defined the "undo" or "redo" commands yet.  They look very
  complicated to define precisely, and other people are working on them right
  now.
</ul>

<p class=XXX>A variety of other issues are also noted in the text, formatted
like this.  Feedback would be appreciated on all of them.

<div class=comments>
<p>TODO:

<ul>
  <li>Scour browser bug trackers to try spotting issues I haven't thought of.

  <li>The wording I use for DOM stuff is not maximally precise.  Really I want
  DOM Core to define nice concepts that I can xref, like "insert a node".  I
  don't want to have to explicitly refer to DOM methods like insertBefore()
  every time I want to move things.

  <li>JavaScript can modify the DOM synchronously in some cases, such as DOM
  mutation events and onunload when moving around iframes and objects.  This
  has to be dealt with somehow.  (Pointed out by Ryosuke Niwa of WebKit:
  <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030730.html>1</a>
  <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030751.html>2</a>)

  <li>What happens if you do something like delete a selection or insert text or
  whatnot in the middle of a surrogate pair?  This could make the content not
  serialize through a character encoding change.

  <li>Some more thought needs to go into what happens to the selection when you
  mutate the DOM.  In some cases the results are pretty arbitrary.  It might
  make sense to do some kind of normalization.

  <li>I'm sloppy about handling things like nodes that don't descend from a
  Document, comments that are children of a Document, that sort of thing.  Not
  essential for prototyping, but needs to be cleaned up eventually.  Mostly we
  should be able to avoid the problems by requiring that everything be
  editable, since that immediately means it has to descend from an element or
  Document (and cannot be parentless itself).

  <li>I need to pay more attention to invisible nodes.  These will have no visual
  effect, but they'll make many algorithms behave differently: decomposing a
  range, block-extending, etc.  Also, need to improve the definition to include
  things like whitespace-only nodes.

  <li>Have to make sure that in all the places where we set a selection, it's
  valid.

  <li>Redefine things in terms of ranges, not selections.

  <li>Allow some type of switch to affect non-editable regions too, perhaps on a
  per-command basis.

  <li>Things like delete, forwardDelete, insertText need to handle non-BMP
  characters.
</ul>

<p>Also TODO: Things that are only implemented by a couple of browsers and may
or may not be useful to spec:

<ul>
  <li>decreaseFontSize, increaseFontSize: Only implemented in Gecko and Opera.

  <li>contentReadOnly, enableInlineTableEditing, enableObjectResizing, heading,
  insertBrOnReturn: MDC docs say not implemented in IE (didn't test).

  <li>readOnly: MDC docs say it's a deprecated equivalent of contentReadOnly,
  so presumably like useCSS but less popular.

  <li>2D-Position, absolutePosition, clearAuthenticationCache, createBookmark,
  insertButton, insertFieldset, insertIframe, insertInput*, insertMarquee,
  insertSelectDropdown, insertSelectListbox, insertTextarea, liveResize,
  multipleSelection, overwrite, print, refresh, saveAs, unbookmark: Mentioned
  in MSDN docs but not MDC, so presumably IE-only.  Some of these seem
  inappropriate or useless, others will bear investigation.

  <li>findString, fontSizeDelta, insertNewlineInQuotedContent, justifyNone,
  print, transpose: There's code for these in WebKit,
  Source/WebCore/editing/EditorCommand.cpp, but I didn't see them mentioned
  elsewhere.  Some might be worth adding.

  <li>unselect: Seems to not be implemented by Gecko or Opera, and IE behaves
  oddly: it seems to collapse the selection instead of removing it.  Will only
  implement if there seems to be demand; it's redundant to
  Selection.removeAllRanges() anyway.
</ul>

<p>Things I haven't looked at that multiple browsers implement:

<ul>
  <li>redo, undo: Needs review of the Google work on this; will probably be
  quite complicated.
</ul>

<p>Also need to look at contenteditable=plaintext-only.
</div>

<p>Things that would be useful to address for the future but aren't important
to fix right now are in comments prefixed with "TODO".



<h2 id=selections>Selections</h2>

<div class=comments>
<p>IE9 and Firefox 6.0a2 allow arbitrary ranges in the selection, which follows
what this spec originally said.  However, this leads to unpleasant corner cases
that authors, implementers, and spec writers all have to deal with, and they
don't make any real sense.  Chrome 14 dev and Opera 11.11 aggressively
normalize selections, like not letting them lie inside empty elements and
things like that, but this is also viewed as a bad idea, because it takes
flexibility away from authors.

<p>So I changed the spec to a made-up compromise
that allows some simplification but doesn't constrain authors much.  See
<a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-June/032072.html>discussion</a>.
Basically it would throw exceptions in some places to try to stop the selection
from containing a range that had a boundary point other than an Element or Text
node, or a boundary point that didn't descend from a Document.

<p>But this meant getRangeAt() had to start returning a copy, not a reference.
Also, it would be prone to things failing weirdly in corner cases.  Perhaps
most significantly, all sorts of problems might arise when DOM mutations
transpire, like if a boundary point's node is removed from its parent and the
mutation rules would place the new boundary point inside a non-Text/Element
node.  And finally, the previously-specified behavior had the advantage of
matching two major implementations, while the new behavior matched no one.  So
I changed it back.

<p>See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=15470">bug
15470</a>.  IE9, Firefox 12.0a1, Chrome 17 dev, and Opera Next 12.00 alpha all
make the range initially null.

<p>For the stuff about <code title="">defaultView</code>, see the comments on
<code title=dom-Document-getSelection><a href=#dom-document-getselection>document.getSelection()</a></code>.
</div>

<p>Every <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a> with a non-null
<code class=external data-anolis-spec=html title=dom-Document-defaultView><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#dom-document-defaultview>defaultView</a></code>
has a unique <code><a href=#selection>Selection</a></code> object associated with it.
<code><a href=#selection>Selection</a></code> objects are known as
<dfn id=concept-selection title=concept-selection>selections</dfn>.  Each <a href=#concept-selection title=concept-selection>selection</a> is
associated with a single <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>, which may be null and is initially null.
This one <a href=#concept-selection title=concept-selection>selection</a> must be shared by all the content of the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>
(though not by nested <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>documents</a>), including any editing hosts in the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>.  <a href=#editing-host title="editing host">Editing hosts</a> that are not
inside a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a> cannot have a <a href=#concept-selection title=concept-selection>selection</a>.

<p class=comments>This is a requirement of the HTML spec.  IE9 and Opera Next
12.00 alpha seem to follow it, while Firefox 12.0a1 and Chrome 17 dev seem not
to.  See <a href=selecttest/Document-open.html>test</a>, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=717339">Mozilla bug</a>, <a href="https://bugs.webkit.org/show_bug.cgi?id=76114">WebKit bug</a>.

<p class=note>A document's selection is a singleton object associated with that
document, so it gets replaced with a new object when <code class=external data-anolis-spec=html title=dom-Document-open><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#dom-document-open>Document.open()</a></code> is called.

<p class=comments>See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=15470">bug 15470</a>.  IE9
and Opera Next 12.00 alpha allow the user to reset the range to null after the
fact by clicking somewhere; Firefox 12.0a1 and Chrome 17 dev do not.  I follow
Gecko/WebKit, because it lessens the chance of getRangeAt(0) throwing.

<p>The user agent should allow the user to change the <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#active-document title="active document">active document</a>'s
<a href=#concept-selection title=concept-selection>selection</a>.  If the user makes any modification to a <a href=#concept-selection title=concept-selection>selection</a>, the user
agent must create a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> with suitable <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a>
and associate the <a href=#concept-selection title=concept-selection>selection</a> with this new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> (not modify the
existing <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>).  The user agent must not allow the user to set a
<a href=#concept-selection title=concept-selection>selection</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to null if it was not already null.

<p class=comments>This matches Firefox 12.0a1, as far as I can tell.  Chrome 17
dev and Opera Next 12.00 alpha return copies from getRangeAt(), so the
requirement isn't testable for them.  IE9 threw weird exceptions in my testing,
so I match the only browser I could test.

<p>Once a <a href=#concept-selection title=concept-selection>selection</a> is associated with a given <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>, it must continue
to be associated with that same <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> until this specification requires
otherwise.

<p class=note>For instance, if the DOM changes in a way that changes the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary points</a>, or a script modifies the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary points</a> of
the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>, the same <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> object must continue to be associated with
the <a href=#concept-selection title=concept-selection>selection</a>.  However, if the user changes the selection or a script
calls <code title=dom-Selection-addRange><a href=#dom-selection-addrange>addRange()</a></code>, the <a href=#concept-selection title=concept-selection>selection</a>
must be associated with a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> object, as required elsewhere in this
specification.

<p class=comments>This paragraph is vague.  It needs to be replaced by detailed
conformance requirements saying exactly what to do for particular keystrokes,
like we have for backspace/delete/etc.

<p>If the <a href=#concept-selection title=concept-selection>selection</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is not null and is <code class=external data-anolis-spec=dom title=dom-Range-collapsed><a href=http://dom.spec.whatwg.org/#dom-range-collapsed>collapsed</a></code>, then
the caret position must be at that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>.  When the
<a href=#concept-selection title=concept-selection>selection</a> is not empty, this specification does not define the caret
position; user agents should follow platform conventions in deciding whether
the caret is at the start of the <a href=#concept-selection title=concept-selection>selection</a>, the end of the <a href=#concept-selection title=concept-selection>selection</a>,
or somewhere else.

<p class=comments>This short-changes Mac users.  See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13909">bug 13909</a>.

<p>Each <a href=#concept-selection title=concept-selection>selection</a> has a <dfn id=concept-selection-dir title=concept-selection-dir>direction</dfn>,
either <i title="">forwards</i> or <i title="">backwards</i>. If the user creates a
<a href=#concept-selection title=concept-selection>selection</a> by indicating first one <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> of the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> and
then the other (such as by clicking on one point and dragging to another), and
the first indicated <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-after title=concept-range-bp-after>after</a> the second, then the
corresponding <a href=#concept-selection title=concept-selection>selection</a> must initially be backwards. Otherwise, it must be
forwards (including if the user didn't create the <a href=#concept-selection title=concept-selection>selection</a>, created it by
selecting an entire part of the page using a keyboard shortcut, etc.).

<p class=XXX>Wouldn't it make more sense if addRange()/removeRange() reset
direction?

<p><a href=#concept-selection title=concept-selection>Selections</a> also have an <dfn id=anchor>anchor</dfn> and a <dfn id=focus>focus</dfn>.  If
the <a href=#concept-selection title=concept-selection>selection</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is null, its <a href=#anchor>anchor</a> and
<a href=#focus>focus</a> are both null.  If the <a href=#concept-selection title=concept-selection>selection</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is not null
and its <a href=#concept-selection-dir title=concept-selection-dir>direction</a> is forwards, its <a href=#anchor>anchor</a> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>'s
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>, and its <a href=#focus>focus</a> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a>.  Otherwise, its
<a href=#focus>focus</a> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> and its <a href=#anchor>anchor</a> is the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a>.

<pre class=idl>interface <dfn id=selection>Selection</dfn> {
  readonly attribute <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#node>Node</a>? <a href=#dom-selection-anchornode title=dom-Selection-anchorNode>anchorNode</a>;
  readonly attribute unsigned long <a href=#dom-selection-anchoroffset title=dom-Selection-anchorOffset>anchorOffset</a>;
  readonly attribute <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#node>Node</a>? <a href=#dom-selection-focusnode title=dom-Selection-focusNode>focusNode</a>;
  readonly attribute unsigned long <a href=#dom-selection-focusoffset title=dom-Selection-focusOffset>focusOffset</a>;

  readonly attribute boolean <a href=#dom-selection-iscollapsed title=dom-Selection-isCollapsed>isCollapsed</a>;
  void               <a href=#dom-selection-collapse title=dom-Selection-collapse>collapse</a>(<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#node>Node</a> node, unsigned long offset);
  void               <a href=#dom-selection-collapsetostart title=dom-Selection-collapseToStart>collapseToStart</a>();
  void               <a href=#dom-selection-collapsetoend title=dom-Selection-collapseToEnd>collapseToEnd</a>();

  void               <a href=#dom-selection-extend title=dom-Selection-extend>extend</a>(<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#node>Node</a> node, unsigned long offset);

  void               <a href=#dom-selection-selectallchildren title=dom-Selection-selectAllChildren>selectAllChildren</a>(<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#node>Node</a> node);
  void               <a href=#dom-selection-deletefromdocument title=dom-Selection-deleteFromDocument>deleteFromDocument</a>();

  readonly attribute unsigned long <a href=#dom-selection-rangecount title=dom-Selection-rangeCount>rangeCount</a>;
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#range>Range</a>              <a href=#dom-selection-getrangeat title=dom-Selection-getRangeAt>getRangeAt</a>(unsigned long index);
  void               <a href=#dom-selection-addrange title=dom-Selection-addRange>addRange</a>(<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#range>Range</a> range);
  void               <a href=#dom-selection-removerange title=dom-Selection-removeRange>removeRange</a>(<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#range>Range</a> range);
  void               <a href=#dom-selection-removeallranges title=dom-Selection-removeAllRanges>removeAllRanges</a>();

  <a href=#dom-selection-stringifier title=dom-Selection-stringifier>stringifier</a>;
};</pre>

<p class=comments>See also <a href=https://mxr.mozilla.org/mozilla/source/content/base/public/nsISelection.idl>nsISelection.idl</a>
from Gecko.  This spec doesn't have everything from there yet, in particular
selectionLanguageChange() and containsNode() are missing. They are missing
because I couldn't work out how to define them in terms of Ranges.

<div class=note>
<p>Originally, the Selection interface was a Netscape feature.  The
original implementation was carried on into Gecko (Firefox), and the feature
was later implemented independently by other browser engines.  The Netscape
implementation always allowed multiple ranges in a single selection, for
instance so the user could select a column of a table.  However, multi-range
selections proved to be an unpleasant corner case that web developers didn't
know about and even Gecko developers rarely handled correctly.  Other browser
engines never implemented the feature, and clamped selections to a single range
in various incompatible fashions.

<p>This specification follows non-Gecko engines in restricting selections to at
most one range, but the API was still originally designed for selections with
arbitrary numbers of ranges.  This explains oddities like the coexistence of
<code title="">removeRange()</code> and <code title="">removeAllRanges()</code>, and a
<code title="">getRangeAt()</code> method that takes an integer argument that must always be
zero.
</div>

<p>All of the members of the <code><a href=#selection>Selection</a></code> interface are defined in
terms of operations on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> object (if any) represented by the object.
These operations can raise exceptions, as defined for the <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#range>Range</a></code> interface; this can therefore result in the
members of the <code><a href=#selection>Selection</a></code> interface raising exceptions as well, in
addition to any explicitly called out below.

<p class=XXX>What happens if you try to put a selection in some node that's not
part of the selection's document?  Assuming it works, how is it presented to
the user?

<p class=XXX>What does <code title="">getSelection().getRangeAt(0).detach()</code> do?

<dl class=domintro>
  <dt><var title="">selection</var> . <code title=dom-Selection-anchorNode><a href=#dom-selection-anchornode>anchorNode</a></code>
  <dd>
    <p>Returns the element that contains the start of the selection.

    <p>Returns null if there's no selection.

  <dt><var title="">selection</var> . <code title=dom-Selection-anchorOffset><a href=#dom-selection-anchoroffset>anchorOffset</a></code>
  <dd>
    <p>Returns the offset of the start of the selection relative to the element
    that contains the start of the selection.

    <p>Returns 0 if there's no selection.

  <dt><var title="">selection</var> . <code title=dom-Selection-focusNode><a href=#dom-selection-focusnode>focusNode</a></code>
  <dd>
    <p>Returns the element that contains the end of the selection.

    <p>Returns null if there's no selection.

  <dt><var title="">selection</var> . <code title=dom-Selection-focusOffset><a href=#dom-selection-focusoffset>focusOffset</a></code>
  <dd>
    <p>Returns the offset of the end of the selection relative to the element
    that contains the end of the selection.

    <p>Returns 0 if there's no selection.
</dl>

<p>The <dfn id=dom-selection-anchornode title=dom-Selection-anchorNode><code>anchorNode</code></dfn>
attribute must return the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#anchor>anchor</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>,
or null if the <a href=#anchor>anchor</a> is null.

<p>The <dfn id=dom-selection-anchoroffset title=dom-Selection-anchorOffset><code>anchorOffset</code></dfn>
attribute must return the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#anchor>anchor</a>'s
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>, or 0 if the <a href=#anchor>anchor</a> is null.

<p>The <dfn id=dom-selection-focusnode title=dom-Selection-focusNode><code>focusNode</code></dfn>
attribute must return the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#focus>focus</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, or
null if the <a href=#focus>focus</a> is null.

<p>The <dfn id=dom-selection-focusoffset title=dom-Selection-focusOffset><code>focusOffset</code></dfn>
attribute must return the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#focus>focus</a>'s
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>, or 0 if the <a href=#focus>focus</a> is null.

<dl class=domintro>
  <dt><var title="">collapsed</var> = <var title="">selection</var> . <code title=dom-Selection-isCollapsed><a href=#dom-selection-iscollapsed>isCollapsed</a></code>()
  <dd>
    <p>Returns true if there's no selection or if the selection is empty.
    Otherwise, returns false.

  <dt><var title="">selection</var> .
  <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse</a></code>(<var title="">node</var>,
  <var title="">offset</var>)
  <dd>
    <p>Replaces the selection with a collapsed one at the given position.

    <p>Throws an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#indexsizeerror>IndexSizeError</a></code> exception if <var title="">offset</var> is negative
    or longer than <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.

  <dt><var title="">selection</var> . <code title=dom-Selection-collapseToStart><a href=#dom-selection-collapsetostart>collapseToStart</a></code>()
  <dd>
    <p>Replaces the selection with an empty one at the position of the start of
    the current selection.

    <p>Throws an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#invalidstateerror>InvalidStateError</a></code> exception if there is no selection.

  <dt><var title="">selection</var> . <code title=dom-Selection-collapseToEnd><a href=#dom-selection-collapsetoend>collapseToEnd</a></code>()
  <dd>
    <p>Replaces the selection with an empty one at the position of the end of
    the current selection.

    <p>Throws an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#invalidstateerror>InvalidStateError</a></code> exception if there is no selection.

  <dt><var title="">selection</var> .
  <code title=dom-Selection-extend><a href=#dom-selection-extend>extend</a></code>(<var title="">node</var>,
  <var title="">offset</var>)
  <dd>
    <p>Changes the <a href=#focus>focus</a> while leaving the <a href=#anchor>anchor</a> in
    place.

    <p>Throws an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#invalidstateerror>InvalidStateError</a></code> if there's no selection, an
    <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#invalidnodetypeerror>InvalidNodeTypeError</a></code> if <var title="">node</var> is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-doctype title=concept-doctype>doctype</a>, and an
    <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#indexsizeerror>IndexSizeError</a></code> exception if <var title="">offset</var> is negative or longer
    than <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.
</dl>

<p>The <dfn id=dom-selection-iscollapsed title=dom-Selection-isCollapsed><code>isCollapsed</code></dfn>
attribute must return true if the <a href=#anchor>anchor</a> and <a href=#focus>focus</a>
are the same (including if both are null).  Otherwise it must return false.

<p>The <dfn id=dom-selection-collapse title=dom-Selection-collapse><code>collapse(<var title="">node</var>,
<var title="">offset</var>)</code></dfn> method must create a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>,
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>set</a> both its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> to
(<var title="">node</var>, <var title="">offset</var>), and set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>
to the newly-created <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>.

<p class=comments>For collapseToStart/End, IE9 mutates the existing range,
while Firefox 9.0a2 and Chrome 15 dev replace it with a new one.  The spec
follows the majority and replaces it with a new one, leaving the old Range
object unchanged.

<p>The <dfn id=dom-selection-collapsetostart title=dom-Selection-collapseToStart><code>collapseToStart()</code></dfn> method
must <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#invalidstateerror>InvalidStateError</a></code> exception if the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is null.  Otherwise, it must create a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> object,
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>set</a> both its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> to the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>, and then set the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to the newly-created <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>.

<p>The <dfn id=dom-selection-collapsetoend title=dom-Selection-collapseToEnd><code>collapseToEnd()</code></dfn> method
must <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#invalidstateerror>InvalidStateError</a></code> exception if the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is null.  Otherwise, it must create a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> object,
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>set</a> both its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> to the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a>, and then set the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to the newly-created <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>.

<p class=comments>Reverse-engineered circa January 2011.  IE doesn't support it, so I'm
relying on Firefox (implemented extend() sometime before 2000) and WebKit
(implemented extend() in 2007).  I'm mostly ignoring Opera, because gsnedders
tells me its implementation isn't compatible.

<p>The <dfn id=dom-selection-extend title=dom-Selection-extend><code>extend(<var title="">node</var>,
<var title="">offset</var>)</code></dfn> method must run these steps:

<ol>
  <li>
  <p class=comments>Gecko raises a nonstandard exception, WebKit initializes to
  a zero-length selection at the given point, Opera silently ignores it.
  Gecko's behavior of throwing wins, but with a standardized exception type.

  <p>If the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is null, <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> an
  <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#invalidstateerror>InvalidStateError</a></code> exception and abort these steps.

  <li>Let <var title="">anchor</var> and <var title="">focus</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
  <a href=#anchor>anchor</a> and <a href=#focus>focus</a>, and let <var title="">new focus</var> be
  the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> (<var title="">node</var>, <var title="">offset</var>).

  <li>
  <p class=comments>Firefox 12.0a1 seems to mutate the existing range.  IE9
  doesn't support extend(), and it's impossible to tell whether Chrome 17 dev
  or Opera Next 12.00 alpha mutate or replace, because getRangeAt() returns a
  copy anyway.  Nevertheless, I go against Gecko here, to be consistent with
  collapse().

  <p>Let <var title="">new range</var> be a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>.

  <li>
  <p class=comments>Gecko sets the direction backwards here.  Why backwards?  I
  don't know.  I'm ignoring direction for collapsed selections for now.

  <p>If <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-root title=concept-tree-root>root</a> is not the same as the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-root title=concept-range-root>root</a>, <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>set</a> <var title="">new range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>
  and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> to (<var title="">node</var>, <var title="">offset</var>).

  <li>Otherwise, if <var title="">anchor</var> is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-before title=concept-range-bp-before>before</a> or equal to
  <var title="">new focus</var>, <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>set</a> <var title="">new range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> to
  <var title="">anchor</var>, then <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>set</a> its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> to
  <var title="">new focus</var>.

  <li>Otherwise, <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>set</a> <var title="">new range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> to <var title="">new
  focus</var>, then <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>set</a> its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> to <var title="">anchor</var>.

  <li>Set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to <var title="">new range</var>.

  <li>If <var title="">new focus</var> is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-before title=concept-range-bp-before>before</a> <var title="">anchor</var>, set the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection-dir title=concept-selection-dir>direction</a> to backwards.  Otherwise, set it to forwards.
</ol>

<p class=comments>Reverse-engineered from WebKit circa January-February 2011.
They were the ones who introduced it, and so far only Gecko has copied them in
Firefox 4, which isn't even a final release yet, so presumably WebKit is the
one to track.  Still, it probably isn't so widely used yet, so I follow Gecko
when it makes more sense.

<hr>

<dl class=domintro>
  <dt><var title="">selection</var> . <code title=dom-Selection-selectAllChildren><a href=#dom-selection-selectallchildren>selectAllChildren</a></code>(<var title="">node</var>)
  <dd>
    <p>Replaces the selection with one that contains all the contents of the
    given element.

  <dt><var title="">selection</var> . <code title=dom-Selection-deleteFromDocument><a href=#dom-selection-deletefromdocument>deleteFromDocument</a></code>()
  <dd>
    <p>Deletes the selection.
</dl>

<div class=comments>
<p>Based mostly on Firefox 9.0a2.  It has a bug that I didn't reproduce, namely
that if you pass a Document as the argument, the end offset becomes 1 instead
of the number of children it has.  It also throws a RangeException instead of
DOMException, because its implementation predated their merging.

<p>IE9 behaves similarly but with glitches.  It throws "Unspecified error." if
the node is detached or display:none, and apparently in some random other cases
too.  It throws "Invalid argument." for detached comments (only!).  Finally, if
you pass it a comment, it seems to select the whole comment, unlike with text
nodes.

<p>Chrome 16 dev behaves as you'd expect given its Selection implementation.
It refuses to select anything that's not visible, so it's almost always wrong.
Opera 11.50 just does nothing in all my tests, as usual.
</div>

<p>The <dfn id=dom-selection-selectallchildren title=dom-Selection-selectAllChildren><code>selectAllChildren(<var title="">node</var>)</code></dfn>
method must run the following steps:

<ol>
  <li>
  <p class=comments>The new range replaces any existing one, doesn't mutate it.
  This matches IE9 and Firefox 12.0a1.  (Chrome 17 dev and Opera Next 12.00
  alpha can't be tested, because getRangeAt() returns a copy anyway.)

  <p>Let <var title="">range</var> be a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>.

  <li><a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>Set</a> <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> to (<var title="">node</var>, 0).

  <li><a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-set title=concept-range-bp-set>Set</a> <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> to (<var title="">node</var>, number
  of <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>).

  <li>Set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to <var title="">range</var>.

  <li>Set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection-dir title=concept-selection-dir>direction</a> to <i title="">forwards</i>.
</ol>

<p class=comments>This is the one method that actually mutates the range
instead of replacing it.  This matches IE9 and Firefox 12.0a1.  (Chrome 17 dev
and Opera Next 12.00 alpha can't be tested, because getRangeAt() returns a copy
anyway.)

<p>The <dfn id=dom-selection-deletefromdocument title=dom-Selection-deleteFromDocument><code>deleteFromDocument()</code></dfn>
method must do nothing if the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is null, and
otherwise must invoke the <code class=external data-anolis-spec=dom title=dom-Range-deleteContents><a href=http://dom.spec.whatwg.org/#dom-range-deletecontents>deleteContents()</a></code> method on the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>.

<p class=XXX>Should we replace the range rather than mutating it here?  This is
currently the only Selection method that actually mutates an existing range in
place.

<dl class=domintro>
  <dt><var title="">selection</var> . <code title=dom-Selection-rangeCount><a href=#dom-selection-rangecount>rangeCount</a></code>
  <dd>
    <p>Returns the number of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>s in the selection (either 0 or 1).

  <dt><var title="">selection</var> . <code title=dom-Selection-getRangeAt><a href=#dom-selection-getrangeat>getRangeAt</a></code>(<var title="">index</var>)
  <dd>
    <p>Returns the selection's <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>, if <var title="">index</var> is 0.

    <p>Throws an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#indexsizeerror>IndexSizeError</a></code> exception if <var title="">index</var> is not 0, or if
    there is no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> in the selection.

  <dt><var title="">selection</var> . <code title=dom-Selection-addRange><a href=#dom-selection-addrange>addRange</a></code>(<var title="">range</var>)
  <dd>
    <p>Adds the given <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to the selection.

  <dt><var title="">selection</var> . <code title=dom-Selection-removeRange><a href=#dom-selection-removerange>removeRange</a></code>(<var title="">range</var>)
  <dd>
    <p>Unselects everyting, if <var title="">range</var> is in the selection.  (Use
    <code title=dom-Selection-removeAllRanges><a href=#dom-selection-removeallranges>removeAllRanges()</a></code> instead.)

  <dt><var title="">selection</var> . <code title=dom-Selection-removeAllRanges><a href=#dom-selection-removeallranges>removeAllRanges</a></code>()
  <dd>
    <p>Unselects everything.
</dl>

<p>The <dfn id=dom-selection-rangecount title=dom-Selection-rangeCount><code>rangeCount</code></dfn>
attribute must return 0 if the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is null, otherwise
1.

<p class=comments>IE9 and Firefox 4.0 return the same object every time, as the
spec says.  Chrome 12 dev and Opera 11.10 return a different object every time.

<p>The <dfn id=dom-selection-getrangeat title=dom-Selection-getRangeAt><code>getRangeAt(<var title="">index</var>)</code></dfn>
method must <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#indexsizeerror>IndexSizeError</a></code> exception if <var title="">index</var> is not
0, or if the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is null.  Otherwise, it must return
a reference to (not a copy of) the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>. (Thus
subsequent calls must return the same object if nothing has removed the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> in the meantime.)

<div class=comments>
<p>IE9 and Firefox 4.0 store a reference, as described here.  Chrome 12 dev and
Opera 11.10 appear to store a copy, so changes don't affect the selection.

<p>Chrome 15 dev seems to ignore addRange() if there's already a range.  IE9
replaces the existing range.  Firefox 9.0a2, of course, just gives you a
multi-range selection.  IE is likely to behave closest to Firefox, and is also
more useful than silent failure, so the spec goes with that.
</div>

<p>The <dfn id=dom-selection-addrange title=dom-Selection-addRange><code>addRange(<var title="">range</var>)</code></dfn>
method must set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to a reference to (not a copy
of) <var title="">range</var>. Since <var title="">range</var> is added by reference, subsequent
calls to <code title=dom-Selection-getRangeAt><a href=#dom-selection-getrangeat>getRangeAt(0)</a></code> must return
the same object, and any changes that a script makes to <var title="">range</var> after
it is added must be reflected in the <a href=#concept-selection title=concept-selection>selection</a>, until something else
removes or replaces the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>.

<p>The <dfn id=dom-selection-removerange title=dom-Selection-removeRange><code>removeRange(<var title="">range</var>)</code></dfn>
method must set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to null if its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> is
currently <var title="">range</var>, otherwise do nothing.

<p class=XXX>Do we check for object equality here or just equality of boundary
points?

<p>The <dfn id=dom-selection-removeallranges title=dom-Selection-removeAllRanges><code>removeAllRanges()</code></dfn> method
must set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to null and its <a href=#concept-selection-dir title=concept-selection-dir>direction</a> to
forwards.

<p>The <dfn id=dom-selection-stringifier title=dom-Selection-stringifier>stringifier</dfn> must . . .

<p class=XXX>Complicated.  The Selection stringifier is magical like innerText.
See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=10583">W3C bug
10583</a>.

<p>This specification extends several interfaces to provide entry points to the
interfaces defined in this specification.

<dl class=domintro>
  <dt><var title="">window</var> . <code title=dom-Window-getSelection><a href=#dom-window-getselection>getSelection</a></code>()
  <dt><var title="">document</var> . <code title=dom-Document-getSelection><a href=#dom-document-getselection>getSelection</a></code>()
  <dd>
    <p>Returns the <code><a href=#selection>Selection</a></code> object for the window, which
    stringifies to the text of the current selection.
</dl>

<pre class=idl>partial interface <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#document>Document</a> {
  <a href=#selection>Selection</a> <a href=#dom-document-getselection title=dom-Document-getSelection>getSelection</a>();
};</pre>

<div class=comments>
<p>Originally Gecko returned the stringification here (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=636512">bug 636512</a> fixed
that).

<p>Now, what happens if you create a Document object with no defaultView
(say via <code title="">document.implementation.createHTMLDocument("")</code>) and call
<code title="">getSelection()</code> on it?  IE9 seems to return a different Selection
object.  Firefox 12.0a1 and Opera Next 12.00 alpha return the same object as
for the current window.  Chrome 17 dev returns null.  See
<a href=https://lists.w3.org/Archives/Public/public-webapps/2012JanMar/0159.html>discussion</a>.
There's no meaningful selection associated with such a document, so we follow
WebKit and require returning null.

<p>This leaves open the question of which documents should actually return
null.  We somewhat cheat by deferring the question to the definition of
<code title="">defaultView</code>, even though at the time of this writing that's
<a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=15548">underdefined and
not very interoperable</a>.
</div>

<p>The <dfn id=dom-document-getselection title=dom-Document-getSelection><code>getSelection()</code></dfn>
method on the <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#document>Document</a></code> interface must return
null if the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <code class=external data-anolis-spec=html title=dom-Document-defaultView><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#dom-document-defaultview>defaultView</a></code> is null, and the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a> otherwise.

<pre class=idl>partial interface <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#window>Window</a> {
  <a href=#selection>Selection</a> <a href=#dom-window-getselection title=dom-Window-getSelection>getSelection</a>();
};</pre>

<p>The <dfn id=dom-window-getselection title=dom-Window-getSelection><code>getSelection()</code></dfn>
method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#window>Window</a></code> interface must return
the same thing as calling
<code title=dom-Document-getSelection><a href=#dom-document-getselection>getSelection()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>
returned by the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
<code class=external data-anolis-spec=html title=dom-document-0><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#dom-document-0>document</a></code> property.


<h2 id=commands>Commands</h2>

<h3 id=properties-of-commands>Properties of commands</h3>

<p>This specification defines a number of <dfn id=command title=command>commands</dfn>,
identified by <a class=external data-anolis-spec=domcore href=http://dom.spec.whatwg.org/#ascii-case-insensitive>ASCII case-insensitive</a>
strings.  Each <a href=#command>command</a> can have several pieces of data associated
with it:

<ul>
  <li><dfn id=action>Action</dfn>: What the <a href=#command>command</a> does when executed via
  <code><a href=#execcommand()>execCommand()</a></code>.  Every <a href=#command>command</a> defined in this
  specification has an <a href=#action>action</a> defined for it in the relevant
  section.  For example, <a href=#the-bold-command>the <code title="">bold</code> command</a>'s
  <a href=#action>action</a> generally makes the current selection bold, or removes
  bold if the selection is already bold.  An editing toolbar might provide
  buttons that execute the <a href=#action>action</a> for a <a href=#command>command</a> if
  clicked, or a script might run an <a href=#action>action</a> without user
  interaction to achieve some particular effect.  Actions return either true or
  false, which can affect the return value of <code><a href=#execcommand()>execCommand()</a></code>.

  <li><dfn id=indeterminate>Indeterminate</dfn>: A boolean value returned by
  <code><a href=#querycommandindeterm()>queryCommandIndeterm()</a></code>, depending on the current state of the
  document.  Generally, a <a href=#command>command</a> that has a <a href=#state>state</a>
  defined will be <a href=#indeterminate>indeterminate</a> if the <a href=#state>state</a> is true
  for part but not all of the current selection, and a <a href=#command>command</a>
  that has a <a href=#value>value</a> defined will be <a href=#indeterminate>indeterminate</a> if
  different parts of the selection have different <a href=#value title=value>values</a>.  An editing toolbar might display a button or
  control in a special way if the <a href=#command>command</a> is
  <a href=#indeterminate>indeterminate</a>, like showing a "bold" button as partially
  depressed, or leaving a font size selector blank instead of showing the font
  size of the current selection.  As a rule, a <a href=#command>command</a> can only be
  <a href=#indeterminate>indeterminate</a> if its <a href=#state>state</a> is false, supposing it
  has a <a href=#state>state</a>.

  <li><dfn id=state>State</dfn>: A boolean value returned by
  <code><a href=#querycommandstate()>queryCommandState()</a></code>, depending on the current state of the
  document.  The <a href=#state>state</a> of a <a href=#command>command</a> is true if it is
  already in effect, in some sense specific to the <a href=#command>command</a>.  Most
  <a href=#command title=command>commands</a> that have a <a href=#state>state</a> defined
  will take opposite <a href=#action title=action>actions</a> depending on whether the
  <a href=#state>state</a> is true or false, such as making the selection bold if the
  <a href=#state>state</a> is false and removing bold if the <a href=#state>state</a> is
  true.  Others will just have no effect if the <a href=#state>state</a> is true,
  like <a href=#the-justifycenter-command>the <code title="">justifyCenter</code> command</a>.  Still others
  will have the same effect regardless, like <a href=#the-stylewithcss-command>the <code title="">styleWithCss</code> command</a>.  An editing toolbar might display a
  button or control differently depending on the <a href=#state>state</a> and <a href=#indeterminate title=indeterminate>indeterminacy</a> of the <a href=#command>command</a>.

  <li><dfn id=value>Value</dfn>: A string returned by <code><a href=#querycommandvalue()>queryCommandValue()</a></code>,
  depending on the current state of the document.  A <a href=#command>command</a>
  usually has a <a href=#value>value</a> instead of a <a href=#state>state</a> if the
  property it modifies can take more than two different values, like <a href=#the-forecolor-command>the
  <code title="">foreColor</code> command</a>.  If the <a href=#command>command</a> is
  <a href=#indeterminate>indeterminate</a>, its <a href=#value>value</a> is generally based on the
  start of the selection.  Otherwise, in most cases the <a href=#value>value</a>
  holds true for the entire selection, but see <a href=#the-justifycenter-command>the <code title="">justifyCenter</code> command</a> and <a href=#the-justifyfull-command title="the justifyFull
  command">its</a> <a href=#the-justifyleft-command title="the justifyLeft command">three</a> <a href=#the-justifyright-command title="the justifyRight command">companions</a> for an exception.  An
  editing toolbar might display the <a href=#value>value</a> of a
  <a href=#command>command</a> as selected in a drop-down or filled in in a text box,
  if the <a href=#command>command</a> isn't <a href=#indeterminate>indeterminate</a>.

  <li><dfn id=relevant-css-property>Relevant CSS property</dfn>: This is defined for certain <a href=#inline-formatting-commands>inline formatting commands</a>, and is used
  in algorithms specific to those commands.  It is an implementation detail,
  and is not exposed to authors.  If a <a href=#command>command</a> does not have a
  <a href=#relevant-css-property>relevant CSS property</a> specified, it defaults to null.
</ul>


<h3 id=supported-commands>Supported commands</h3>

<p class=comments>If you try doing anything with an unrecognized command
(except queryCommandSupported), IE10 Developer Preview throws an "Invalid
argument" exception.  Firefox 15.0a1 throws NS_ERROR_NOT_IMPLEMENTED on
querying indeterm/state/value, and returns false from
execCommand/queryCommandEnabled.  Chrome 19 dev returns false from everything.
Opera Next 12.00 alpha throws NOT_SUPPORTED_ERR for execCommand and returns
false for enabled/state/value.  Originally I went with IE, although of course
with a standard exception type.  But after discussion (<a href="https://bugs.webkit.org/show_bug.cgi?id=83993">WebKit bug</a>, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=742240">Mozilla bug</a>), I
changed to match WebKit (except that I return "" for value instead of false).
The issue is that there are a whole bunch of IE commands that no one else
supports or wants to support, and throwing on execCommand() would make lots of
pages break.  WebKit was unwilling to take the compat risk, so we took the
safer option.

<p>Some <a href=#command title=command>commands</a> will be <dfn id=supported>supported</dfn> in a
given user agent, and some will not.  All <a href=#command title=command>commands</a>
defined in this specification must be <a href=#supported>supported</a>, except optionally
<a href=#the-copy-command>the <code title="">copy</code> command</a>, <a href=#the-cut-command>the <code title="">cut</code> command</a>, and/or <a href=#the-paste-command>the <code title="">paste</code>
command</a>.  Additional
<dfn id=vendor-specific-command title="vendor-specific command">vendor-specific commands</dfn> can also be
<a href=#supported>supported</a>, but implementers must prefix any
<a href=#vendor-specific-command>vendor-specific command</a> names with a vendor-specific string (e.g.,
"ms", "moz", "webkit", "opera").

<p class=comments>I.e., no trying to look good on lazy conformance tests by
just sticking in a stub implementation that does nothing.

<p>A <a href=#command>command</a> that does absolutely nothing in a particular user
agent, such that <code><a href=#execcommand()>execCommand()</a></code> never has any effect and
<code><a href=#querycommandenabled()>queryCommandEnabled()</a></code> and <code><a href=#querycommandindeterm()>queryCommandIndeterm()</a></code> and
<code><a href=#querycommandstate()>queryCommandState()</a></code> and <code><a href=#querycommandvalue()>queryCommandValue()</a></code> each
return the same value all the time, must not be <a href=#supported>supported</a>.


<p>In a particular user agent, every <a href=#command>command</a> must be consistently
either <a href=#supported>supported</a> or not.  Specifically, a user agent must not
permit one page to see the same <a href=#command>command</a> sometimes
<a href=#supported>supported</a> and sometimes not over the course of the same browsing
session, unless the user agent has been upgraded or reconfigured in the middle
of a session.  However, user agents may treat the same <a href=#command>command</a> as
<a href=#supported>supported</a> for some pages and not others, e.g., if the
<a href=#command>command</a> is only supported for certain origins for security
reasons.

<p>Authors can tell whether a <a href=#command>command</a> is <a href=#supported>supported</a>
using <code><a href=#querycommandsupported()>queryCommandSupported()</a></code>.


<h3 id=enabled-commands>Enabled commands</h3>

<p>At any given time, a <a href=#supported>supported</a> command can be either
<dfn id=enabled>enabled</dfn> or not.  Authors can tell whether a <a href=#command>command</a> is
currently <a href=#enabled>enabled</a> using <code><a href=#querycommandenabled()>queryCommandEnabled()</a></code>.  <a href=#command title=command>Commands</a> that are not <a href=#enabled>enabled</a> do nothing, as
described in the definitions of the various methods that invoke <a href=#command title=command>commands</a>.

<div class=comments>
<p>Testing with bold:

<p>IE10PP2 seems to return true if the active range's start node is editable,
false otherwise.

<p>Firefox 6.0a2 seems to always return true if there's anything editable on the
page, and throw otherwise.  (This is <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=676401">bug 676401</a>.)

<p>Chrome 14 dev seems to behave the same as IE10PP2.

<p>Opera 11.11 seems to always return true if there's anything editable on the
page, and false otherwise.

<p>Firefox and Opera behave more or less uselessly.  IE doesn't make much sense,
in that whether a command is enabled seems meaningless: it will execute it on
all nodes in the selection, editable or not.  Chrome's definition makes sense
in that it will only run the command if it's enabled, but it doesn't make much
sense to only have the command run if the start is editable.

<p>It's not clear to me what the point of this method is.  There's no way we're
going to always return true if the command will do something and false if it
won't.  I originally just stuck with a really conservative definition that happens to be
convenient: if there's nothing selected, obviously nothing will work, and we
want to bail out early in that case anyway because all the algorithms will talk
about the active range.  If there are use-cases for it to be more precise, I
could make it so.

<p><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=16094">Bug 16094</a>
illustrated that we don't really want to be able to modify multiple editing
hosts at once, nor do we want to do anything if the start and end aren't both
editable, so I co-opted this definition to fit my ends.
</div>

<p>Among <a href=#command title=command>commands</a> defined in this specification,
those listed in <a href=#miscellaneous-commands>Miscellaneous commands</a> are
always <a href=#enabled>enabled</a>, except for <a href=#the-cut-command>the <code title="">cut</code>
command</a> and <a href=#the-paste-command>the <code title="">paste</code> command</a>.  The
other <a href=#command title=command>commands</a> defined here are <a href=#enabled>enabled</a>
if the <a href=#active-range>active range</a> is not null, its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is either
<a href=#editable>editable</a> or an <a href=#editing-host>editing host</a>, its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a> is
either <a href=#editable>editable</a> or an <a href=#editing-host>editing host</a>, and there is some
<a href=#editing-host>editing host</a> that is an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> of both its
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>.



<h2 id=methods-to-query-and-execute-commands>Methods to query and execute commands</h2>

<p class=XXX>We fire events as requested in
<a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13118">bug 13118</a>.
This is a new feature does not currently match any browser.  <strong>If you are
implementing this, please make sure to file any feedback as bugs.  The spec is
not finalized yet and can still be easily changed.</strong>

<pre class=idl>[Constructor(DOMString <var title="">type</var>, optional <a href=#editingbeforeinputeventinit>EditingBeforeInputEventInit</a> <var title="">eventInitDict</var>)]
interface <dfn id=editingbeforeinputevent>EditingBeforeInputEvent</dfn> : <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#event>Event</a> {
  readonly attribute DOMString <a href=#dom-editingbeforeinputevent-command title=dom-EditingBeforeInputEvent-command>command</a>;
  readonly attribute DOMString <a href=#dom-editingbeforeinputevent-value title=dom-EditingBeforeInputEvent-value>value</a>;
};

dictionary <dfn id=editingbeforeinputeventinit>EditingBeforeInputEventInit</dfn> : <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#eventinit>EventInit</a> {
  DOMString command;
  DOMString value;
};

[Constructor(DOMString <var title="">type</var>, optional <a href=#editinginputeventinit>EditingInputEventInit</a> <var title="">eventInitDict</var>)]
interface <dfn id=editinginputevent>EditingInputEvent</dfn> : <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#event>Event</a> {
  readonly attribute DOMString <a href=#dom-editinginputevent-command title=dom-EditingInputEvent-command>command</a>;
  readonly attribute DOMString <a href=#dom-editinginputevent-value title=dom-EditingInputEvent-value>value</a>;
};

dictionary <dfn id=editinginputeventinit>EditingInputEventInit</dfn> : <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#eventinit>EventInit</a> {
  DOMString command;
  DOMString value;
};</pre>

<p class=XXX>We have two different interfaces because we might want to add
additional members to the input event but not the beforeinput event, such as a
list of nodes that were affected.

<p>When an <code><a href=#editingbeforeinputevent>EditingBeforeInputEvent</a></code> object is created, the
<dfn id=dom-editingbeforeinputevent-command title=dom-EditingBeforeInputEvent-command><code>command</code></dfn> and
<dfn id=dom-editingbeforeinputevent-value title=dom-EditingBeforeInputEvent-value><code>value</code></dfn>
attributes must both be initialized to the empty string, unless otherwise
specified.

<p>When an <code><a href=#editinginputevent>EditingInputEvent</a></code> object is created, the
<dfn id=dom-editinginputevent-command title=dom-EditingInputEvent-command><code>command</code></dfn> and
<dfn id=dom-editinginputevent-value title=dom-EditingInputEvent-value><code>value</code></dfn> attributes must
both be initialized to the empty string, unless otherwise specified.

<p class=comments>TODO: Define behavior for <var title="">show UI</var>.

<p>When the <dfn id=execcommand() title=execCommand()><code>execCommand(<var title="">command</var>,
<var title="">show UI</var>, <var title="">value</var>)</code></dfn> method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> interface is invoked, the user agent
must run the following steps:

<ol>
  <li>If only one argument was provided, let <var title="">show UI</var> be false.

  <li>If only one or two arguments were provided, let <var title="">value</var> be the
  empty string.

  <li>
  <div class=comments>
  <p>For supported: see comment before <a href=#supported-commands>Supported
  commands</a>.

  <p>For enabled: I didn't research this closely, but at a first glance, this
  is possibly how Chrome 14 dev and Opera 11.11 behave.  Maybe also Firefox
  6.0a2, except it throws if the command isn't enabled, I think.  IE9 returns
  true in at least some cases even if the command is disabled.  TODO: Is this
  right?  Maybe we should be returning false in other cases too?
  </div>

  <p>If <var title="">command</var> is not <a href=#supported>supported</a> or not
  <a href=#enabled>enabled</a>, return false.

  <li>
  <p>If <var title="">command</var> is not in the
  <a href=#miscellaneous-commands>Miscellaneous commands</a> section:

  <p class=XXX>We don't fire events for copy/cut/paste/undo/redo/selectAll
  because they should all have their own events.  We don't fire events for
  styleWithCSS/useCSS because it's not obvious where to fire them, or why
  anyone would want them.  We don't fire events for unsupported commands,
  because then if they became supported and were classified with the
  miscellaneous events, we'd have to stop firing events for consistency's sake.

  <ol>
    <li>Let <var title="">affected editing host</var> be the <a href=#editing-host>editing host</a>
    that is an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> of the <a href=#active-range>active range</a>'s
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>, and is not the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of any
    <a href=#editing-host>editing host</a> that is an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> of the
    <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>.

    <p class=note>Such an editing host must exist, because otherwise the
    command would not be <a href=#enabled>enabled</a>.

    <li><a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-event-dispatch title=concept-event-dispatch>Dispatch</a> an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-event title=concept-event>event</a> at <var title="">affected editing host</var> that uses
    the <code><a href=#editingbeforeinputevent>EditingBeforeInputEvent</a></code> interface.  The event's
    <code class=external data-anolis-spec=dom title=dom-Event-type><a href=http://dom.spec.whatwg.org/#dom-event-type>type</a></code> attribute must
    be initialized to "beforeinput"; its
    <code class=external data-anolis-spec=dom title=dom-Event-isTrusted><a href=http://dom.spec.whatwg.org/#dom-event-istrusted>isTrusted</a></code>,
    <code class=external data-anolis-spec=dom title=dom-Event-bubbles><a href=http://dom.spec.whatwg.org/#dom-event-bubbles>bubbles</a></code>, and
    <code class=external data-anolis-spec=dom title=dom-Event-cancelable><a href=http://dom.spec.whatwg.org/#dom-event-cancelable>cancelable</a></code>
    attributes must be initialized to true; its
    <code title=dom-EditingBeforeInputEvent-command><a href=#dom-editingbeforeinputevent-command>command</a></code> attribute
    must be initialized to <var title="">command</var>; and its
    <code title=dom-EditingBeforeInputEvent-value><a href=#dom-editingbeforeinputevent-value>value</a></code> attribute must
    be initialized to <var title="">value</var>.

    <li>If the value returned by the previous step is false, return false.

    <li>If <var title="">command</var> is not <a href=#enabled>enabled</a>, return false.

    <p class=XXX>We have to check again whether the command is enabled, because
    the beforeinput handler might have done something annoying like
    getSelection().removeAllRanges().

    <li>Let <var title="">affected editing host</var> be the <a href=#editing-host>editing host</a>
    that is an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> of the <a href=#active-range>active range</a>'s
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>, and is not the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of any
    <a href=#editing-host>editing host</a> that is an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> of the
    <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>.

    <p class=XXX>This new affected editing host is what we'll fire the input
    event at in a couple of lines.  We want to compute it beforehand just to be
    safe: bugs in the command action might remove the selection or something
    bad like that, and we don't want to have to handle it later.  We recompute
    it after the beforeinput event is handled so that if the handler moves the
    selection to some other editing host, the input event will be fired at the
    editing host that was actually affected.
  </ol>

  <li>Take the <a href=#action>action</a> for <var title="">command</var>, passing
  <var title="">value</var> to the instructions as an argument.

  <li>If the previous step returned false, return false.

  <li>If <var title="">command</var> is not in the
  <a href=#miscellaneous-commands>Miscellaneous commands</a> section, then
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-event-dispatch title=concept-event-dispatch>dispatch</a> an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-event title=concept-event>event</a> at <var title="">affected editing host</var> that uses the
  <code><a href=#editinginputevent>EditingInputEvent</a></code> interface.  The event's
  <code class=external data-anolis-spec=dom title=dom-Event-type><a href=http://dom.spec.whatwg.org/#dom-event-type>type</a></code> attribute must be
  initialized to "input"; its
  <code class=external data-anolis-spec=dom title=dom-Event-isTrusted><a href=http://dom.spec.whatwg.org/#dom-event-istrusted>isTrusted</a></code> and
  <code class=external data-anolis-spec=dom title=dom-Event-bubbles><a href=http://dom.spec.whatwg.org/#dom-event-bubbles>bubbles</a></code> attributes
  must be initialized to true; its
  <code title=dom-EditingInputEvent-command><a href=#dom-editinginputevent-command>command</a></code> attribute must be
  initialized to <var title="">command</var>; and its
  <code title=dom-EditingInputEvent-value><a href=#dom-editinginputevent-value>value</a></code> attribute must be
  initialized to <var title="">value</var>.

  <li>Return true.
</ol>

<p>When the <dfn id=querycommandenabled() title=queryCommandEnabled()><code>queryCommandEnabled(<var title="">command</var>)</code></dfn>
method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> interface is
invoked, the user agent must run the following steps:

<ol>
  <li>
  <p class=comments>See comment before <a href=#supported-commands>Supported
  commands</a>.

  <li>Return true if <var title="">command</var> is both <a href=#supported>supported</a> and
  <a href=#enabled>enabled</a>, false otherwise.
</ol>

<p>When the <dfn id=querycommandindeterm() title=queryCommandIndeterm()><code>queryCommandIndeterm(<var title="">command</var>)</code></dfn>
method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> interface is
invoked, the user agent must run the following steps:

<ol>
  <li>
  <div class=comments>
  <p>For supported: see comment before <a href=#supported-commands>Supported
  commands</a>.

  <p>What happens if you call queryCommand(Indeterm|State|Value)() on a command
  where it makes no sense?

  <p>IE9 consistently returns false for all three.  However, any command that
  has a state defined also has a value defined, which is equal to the state: it
  returns boolean true or false.

  <p>Firefox 6.0a2 consistently throws NS_ERROR_FAILURE for indeterm/state if
  not supported, and returns an empty string for value.  Exceptions include
  unlink (seems to always return indeterm/state false), and styleWithCss/useCss
  (throw NS_ERROR_FAILURE even for value).

  <p>Chrome 14 dev returns false for all three, and even does this for
  unrecognized commands.  It also always defines value if state is defined: it
  returns the state cast to a string, either "true" or "false".

  <p>Opera 11.11 returns false for state and "" for value (it doesn't support
  indeterm).  Like Chrome, this is even for unrecognized commands.

  <p>Gecko's behavior is the most useful.  If the author tries querying some
  aspect of a command that makes no sense, they shouldn't receive a value that
  looks like it might make sense but is actually just a constant.  Originally,
  I went even further than Gecko: I required exceptions even for value, since
  doing otherwise makes no sense.  But throwing more exceptions is less
  compatible on the whole than throwing more exceptions, so based on <a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-September/033235.html>discussion</a>,
  I switched to a behavior more like Opera, which is more or less IE/WebKit
  behavior but made slightly more sane.
  </div>

  <p>If <var title="">command</var> is not <a href=#supported>supported</a> or has no <a href=#indeterminate title=indeterminate>indeterminacy</a>, return false.

  <li>Return true if <var title="">command</var> is <a href=#indeterminate>indeterminate</a>,
  otherwise false.
</ol>

<p>When the <dfn id=querycommandstate() title=queryCommandState()><code>queryCommandState(<var title="">command</var>)</code></dfn>
method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> interface is
invoked, the user agent must run the following steps:

<ol>
  <li>
  <p class=comments>See comment on the comparable line for
  <a href=#querycommandindeterm()>queryCommandIndeterm()</a>.

  <p>If <var title="">command</var> is not <a href=#supported>supported</a> or has no
  <a href=#state>state</a>, return false.

  <li>If the <a href=#state-override>state override</a> for <var title="">command</var> is set, return
  it.

  <li>Return true if <var title="">command</var>'s <a href=#state>state</a> is true, otherwise
  false.
</ol>

<div class=comments>
<p>Firefox 6.0a2 always throws an exception when this is called.  Opera 11.11
seems to return false if there's nothing editable on the page, which is
unhelpful.  The spec follows IE9 and Chrome 14 dev.  The reason this is useful,
compared to just running one of the other methods and seeing if you get a
NOT_SUPPORTED_ERR, is that other methods might throw different exceptions for
other reasons.  It's easier to check a boolean than to check exception types,
especially since as of June 2011 UAs aren't remotely consistent on what they do
with unsupported commands.

<p>Actually, correction: Firefox &lt; 15ish throws an exception if nothing
editable is on the page.  Otherwise it behaves just like IE/Chrome.  See <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=742240">Mozilla bug
742240</a>.
</div>

<p>When the <dfn id=querycommandsupported() title=queryCommandSupported()><code>queryCommandSupported(<var title="">command</var>)</code></dfn>
method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> interface is
invoked, the user agent must return true if <var title="">command</var> is
<a href=#supported>supported</a>, and false otherwise.

<p>When the <dfn id=querycommandvalue() title=queryCommandValue()><code>queryCommandValue(<var title="">command</var>)</code></dfn>
method on the <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> interface is
invoked, the user agent must run the following steps:

<ol>
  <li>
  <p class=comments>This is what Firefox 6.0a2 and Opera 11.11 seem to do when
  the command isn't enabled.  Chrome 14 dev seems to return the string "false",
  and IE9 seems to return boolean false.  For the case where there's no value,
  or the command isn't supported, see the comment on the comparable line for
  <a href=#querycommandindeterm()>queryCommandIndeterm()</a>.

  <p>If <var title="">command</var> is not <a href=#supported>supported</a> or has no
  <a href=#value>value</a>, return the empty string.

  <li>
  <p class=comments>Yuck.  This is incredibly messy, as are lots of other
  fontSize-related things, but I don't want to define a whole second notion of
  value for the sake of a single command . . .

  <p>If <var title="">command</var> is "fontSize" and its <a href=#value-override>value override</a>
  is set, convert the <a href=#value-override>value override</a> to an integer number of
  pixels and return the <a href=#legacy-font-size-for>legacy font size for</a> the result.

  <li>If the <a href=#value-override>value override</a> for <var title="">command</var> is set, return
  it.

  <li>Return <var title="">command</var>'s <a href=#value>value</a>.
</ol>

<p>All of these methods must treat their <var title="">command</var> argument <a class=external data-anolis-spec=domcore href=http://dom.spec.whatwg.org/#ascii-case-insensitive title="ASCII case-insensitive">ASCII
case-insensitively</a>.

<div class=note>
<p>The methods in this section have mostly been designed so that the following
invariants hold after <code title="">execCommand()</code> is called, assuming it
didn't throw an exception:

<ul>
  <li><code title="">queryCommandIndeterm()</code> will return false (or throw an
  exception).

  <li><code title="">queryCommandState()</code> will return the opposite of what it did
  before <code title="">execCommand()</code> was called (or throw an exception).

  <li><code title="">queryCommandValue()</code> will return something equivalent to the
  value passed to <code title="">execCommand()</code> (or throw an exception).
  "Equivalent" here needs to be construed broadly in some cases, such as
  <code title="">fontSize</code>.
</ul>

<p>The first two points do not always hold for <code title="">strikethrough</code>
or <code title="">underline</code>, because it can be impossible to unset
text-decoration in CSS.  Also, by design, the state of <code title="">insertOrderedList</code> and <code title="">insertUnorderedList</code> might
be true both before and after calling, because they only remove one level of
indentation.  <code title="">unlink</code> should set the value to null.  And
finally, the state of the various <code title="">justify</code> commands should
always be true after calling, and the value should always be the appropriate
string ("center", "justify", "left", or "right").  Any other deviations from
these invariants are bugs in the specification.
</div>


<h2 id=common-definitions>Common definitions</h2>

<p>An <dfn id=html-element>HTML element</dfn> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-namespace title=concept-element-namespace>namespace</a> is the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#html-namespace>HTML namespace</a>.

<p>A <dfn id=prohibited-paragraph-child-name>prohibited paragraph child name</dfn> is "address", "article",
"aside", "blockquote", "caption", "center", "col", "colgroup", "dd", "details",
"dir", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form",
"h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "listing",
"menu", "nav", "ol", "p", "plaintext", "pre", "section", "summary", "table",
"tbody", "td", "tfoot", "th", "thead", "tr", "ul", or "xmp".

<p class=comments>These are all the things that will close a &lt;p&gt; if found as
a descendant.  I think.  Plus table stuff, since that can't be a descendant of
a p either, although it won't auto-close it.

<p>A <dfn id=prohibited-paragraph-child>prohibited paragraph child</dfn> is an <a href=#html-element>HTML element</a>
whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is a <a href=#prohibited-paragraph-child-name>prohibited paragraph child name</a>.

<p class=comments>The block/inline node definitions are CSS-based.  "Prohibited
paragraph child" is conceptually similar to "block node", but based on the
element name.  Generally we want to use block/inline node when we're interested
in the visual effect, and prohibited paragraph children when we're concerned
about parsing or semantics.  TODO: Audit all "block node" usages to see if they
need to become "visible block node", now that block nodes can be invisible (if
they descend from display: none).

<p>A <dfn id=block-node>block node</dfn> is either an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> whose "display" property
does not have <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> "inline" or "inline-block" or "inline-table" or
"none", or a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>, or a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#documentfragment>DocumentFragment</a></code>.

<p>An <dfn id=inline-node>inline node</dfn> is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is not a <a href=#block-node>block
node</a>.

<p>An <dfn id=editing-host>editing host</dfn> is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is either an <a href=#html-element>HTML
element</a> with a <code class=external data-anolis-spec=html title=attr-contenteditable><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#attr-contenteditable>contenteditable</a></code> attribute set to the true
state, or the <a href=#html-element>HTML element</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a> whose <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#designMode>designMode</a></code> is enabled.

<p>Something is <dfn id=editable>editable</dfn> if it is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>; it is not an
<a href=#editing-host>editing host</a>; it does not have a <code class=external data-anolis-spec=html title=attr-contenteditable><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#attr-contenteditable>contenteditable</a></code> attribute set to the false
state; its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <a href=#editing-host>editing host</a> or <a href=#editable>editable</a>;
and either it is an <a href=#html-element>HTML element</a>, or it is an <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/the-map-element.html#svg>svg</a></code> or <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/the-map-element.html#math>math</a></code>
element, or it is not an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <a href=#html-element>HTML
element</a>.

<p class=note>An <a href=#editable>editable</a> node cannot be a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a> or
<code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#documentfragment>DocumentFragment</a></code>, its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> cannot be null, and it must descend from
either an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> or a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>.

<p>The <dfn id=editing-host-of>editing host of</dfn> <var title="">node</var> is null if <var title="">node</var> is
neither <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>; <var title="">node</var>
itself, if <var title="">node</var> is an <a href=#editing-host>editing host</a>; or the nearest
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var> that is an <a href=#editing-host>editing host</a>, if
<var title="">node</var> is <a href=#editable>editable</a>.

<p>Two <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> are <dfn id=in-the-same-editing-host>in the same editing host</dfn> if the <a href=#editing-host-of>editing
host of</a> the first is non-null and the same as the <a href=#editing-host-of>editing host
of</a> the second.

<p class=note>Barring bugs, the algorithms here will not alter the attributes
of a non-editable element; will not remove a non-editable node from its parent
(except to immediately give it a new parent in the same editing host); and will
not add, remove, or reorder children of a node unless it is either editable or
an editing host.  An editing host is never editable, so authors are assured
that editing commands will only modify the editing host's contents and not the
editing host itself.

<p>A <dfn id=collapsed-line-break>collapsed line break</dfn> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> that begins a line box which
has nothing else in it, and therefore has zero height.

<p class=XXX>Is this a good definition at all?  I mean things like
&lt;p&gt;foo&lt;br&gt;&lt;/p&gt;, or the second one in &lt;p&gt;foo&lt;br&gt;&lt;br&gt;&lt;/p&gt;.
The way I test it is by adding a text node after it containing a zwsp; if that
changes the offsetHeight of its nearest non-inline ancestor, I deem it
collapsed.  But what if it happens to be display: none right now, for instance?
Or its ancestor has a fixed height?  Would it be better to use some DOM-based
definition?

<p class=comments>TODO: The thing about li is a not very nice hack.  The issue
is that an li won't collapse even if it has no children at all, but that's not
true in all browsers (at least not in Opera 11.11), and also it breaks
assumptions elsewhere.  E.g., if it gets turned into a p.

<p>An <dfn id=extraneous-line-break>extraneous line break</dfn> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> that has no visual effect,
in that removing it from the DOM would not change layout, except that a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>
that is the sole child of an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> is not extraneous.

<p class=XXX>Also possibly a bad definition.  Again, I test by just removing it
and seeing what happens.  (Actually, setting display: none, so that it doesn't
mess up ranges.)

<p>A <dfn id=whitespace-node>whitespace node</dfn> is either a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node whose <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> is
the empty string; or a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node whose <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> consists only of one or
more tabs (0x0009), line feeds (0x000A), carriage returns (0x000D), and/or
spaces (0x0020), and whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> whose <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> for
"white-space" is "normal" or "nowrap"; or a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node whose <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code>
consists only of one or more tabs (0x0009), carriage returns (0x000D), and/or
spaces (0x0020), and whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> whose <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> for
"white-space" is "pre-line".

<p><var title="">node</var> is a <dfn id=collapsed-whitespace-node>collapsed whitespace node</dfn> if the following
algorithm returns true:

<p class=XXX>This definition is also bad.  It's a crude attempt to emulate
CSS2.1 16.6.1, but leaving out a ton of the subtleties.  I actually don't want
the exact CSS definitions, because those depend on things like where lines are
broken, but I'm not sure this definition is right anyway.  E.g., what about a
pre-line text node consisting of a single line break that's at the end of a
block?  That collapses, same idea as an extraneous line break.  We could also
worry about nodes containing only zwsp or such if we wanted, or display: none,
or . . .

<ol>
  <li>If <var title="">node</var> is not a <a href=#whitespace-node>whitespace node</a>, return false.

  <li>If <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> is the empty string, return true.

  <li>Let <var title="">ancestor</var> be <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If <var title="">ancestor</var> is null, return true.

  <li>If the "display" property of some <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var> has
  <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> "none", return true.

  <li>While <var title="">ancestor</var> is not a <a href=#block-node>block node</a> and its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set <var title="">ancestor</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>
  <div class=comments>
  <p>At this point we know <var title="">node</var> consists of some whitespace, of a
  sort that will collapse if it's at the start or end of a line.  We go
  backwards until we find the first block boundary, and if everything until
  there is invisible or whitespace, we conclude that <var title="">node</var> is
  collapsed.  We assume a block boundary is either when we hit a line break or
  block node, or we hit the end of <var title="">ancestor</var> (which is the nearest
  ancestor block node).  All this is very imprecise, of course, but it's fairly
  simple and will work in common cases.

  <p>We have to avoid invoking the definition of "visible" here to avoid
  infinite recursion: that depends on the concept of collapsed whitespace
  nodes.  Instead, we repeat the parts we need, which turns out to be "not
  much of it".
  </div>

  <p>Let <var title="">reference</var> be <var title="">node</var>.

  <li>While <var title="">reference</var> is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">ancestor</var>:

  <ol>
    <li>Let <var title="">reference</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> before it in <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a>.

    <li>If <var title="">reference</var> is a <a href=#block-node>block node</a> or a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>,
    return true.

    <li>If <var title="">reference</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node that is not a
    <a href=#whitespace-node>whitespace node</a>, or is an <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#the-img-element>img</a></code>, break from this loop.
  </ol>

  <li><p class=comments>We found something before our text node on (probably)
  the same line, so presumably it's not at the line's start.  Now we need to
  look forward and see if we're at the line's end.  If we aren't there either,
  then we assume we're not collapsed, so return false.

  <p>Let <var title="">reference</var> be <var title="">node</var>.

  <li>While <var title="">reference</var> is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">ancestor</var>:

  <ol>
    <li>Let <var title="">reference</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> after it in <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a>, or
    null if there is no such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>.

    <li>If <var title="">reference</var> is a <a href=#block-node>block node</a> or a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>,
    return true.

    <li>If <var title="">reference</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node that is not a
    <a href=#whitespace-node>whitespace node</a>, or is an <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#the-img-element>img</a></code>, break from this loop.
  </ol>

  <li>Return false.
</ol>

<p class=comments>TODO: Consider whether we really want to depend on img
specifically here.  It seems more likely that we want something like "any
replaced content that has nonzero height and width" or such.  When fixing this,
make sure to audit for other occurrences of this assumption.

<p>Something is <dfn id=visible>visible</dfn> if it is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that either is a
<a href=#block-node>block node</a>, or a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node that is not a <a href=#collapsed-whitespace-node>collapsed
whitespace node</a>, or an <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#the-img-element>img</a></code>, or a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> that is not an
<a href=#extraneous-line-break>extraneous line break</a>, or any <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> with a <a href=#visible>visible</a>
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a>; excluding any <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> with an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a>
<code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> whose "display" property has <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> "none".

<p>Something is <dfn id=invisible>invisible</dfn> if it is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is not
<a href=#visible>visible</a>.

<p class=comments>TODO: Reconsider whether we want to lump invisible nodes in
here.  If we don't and change the definition, make sure to audit all callers,
since then a block could have collapsed block prop descendants that aren't
children.

<p>A <dfn id=collapsed-block-prop>collapsed block prop</dfn> is either a <a href=#collapsed-line-break>collapsed line
break</a> that is not an <a href=#extraneous-line-break>extraneous line break</a>, or an
<code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> that is an <a href=#inline-node>inline node</a> and whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> are all
either <a href=#invisible>invisible</a> or <a href=#collapsed-block-prop title="collapsed block prop">collapsed
block props</a> and that has at least one <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> that is a
<a href=#collapsed-block-prop>collapsed block prop</a>.

<p class=note>A collapsed block prop is something like the <code title="">&lt;br&gt;</code> in <code title="">&lt;p&gt;&lt;br&gt;&lt;/p&gt;</code>, or the <code title="">&lt;br&gt;</code> and <code title="">&lt;span&gt;</code> in <code title="">&lt;p&gt;&lt;span&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;</code>.  These are necessary to
stop the block from having zero height when it has no other contents, but serve
no purpose and should be removed once the block has other contents that stop it
from collapsing.

<p class=comments>TODO: I say "first range" because I think that's what Gecko
actually does, and Gecko is the only one that allows multiple ranges in a
selection.  This is keeping in mind that it stores ranges sorted by start, not
by the order the user added them, and silently removes or shortens existing
ranges to avoid overlap.  It probably makes the most sense in the long term to
have the command affect all ranges.  But I'll leave this for later.

<p>The <dfn id=active-range>active range</dfn> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> of the <a href=#concept-selection title=concept-selection>selection</a> given by
calling <code title=dom-Document-getSelection><a href=#dom-document-getselection>getSelection()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.  (Thus the <a href=#active-range>active
range</a> may be null.)

<p>Each <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> has a boolean <dfn id=css-styling-flag>CSS styling flag</dfn> associated
with it, which must initially be false.  (<a href=#the-stylewithcss-command>The <code title="">styleWithCSS</code> command</a> can be used to modify or query it, by
means of the <code><a href=#execcommand()>execCommand()</a></code> and <code><a href=#querycommandstate()>queryCommandState()</a></code>
methods.)

<p>Each <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> is associated with a string known as the
<dfn id=default-single-line-container-name>default single-line container name</dfn>, which must initially be "p".
(<a href=#the-defaultparagraphseparator-command>The <code title="">defaultParagraphSeparator</code> command</a> can be
used to modify or query it, by means of the <code><a href=#execcommand()>execCommand()</a></code> and
<code><a href=#querycommandvalue()>queryCommandValue()</a></code> methods.)

<p>For some <a href=#command title=command>commands</a>, each <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#htmldocument>HTMLDocument</a></code> must
have a boolean <dfn id=state-override>state override</dfn> and/or a string <dfn id=value-override>value
override</dfn>.  These do not change the <a href=#command>command</a>'s
<a href=#state>state</a> or <a href=#value>value</a>, but change the way some algorithms
behave, as specified in those algorithms' definitions.  Initially, both must be
unset for every <a href=#command>command</a>.  Whenever the number of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>ranges</a> in the
<a href=#concept-selection title=concept-selection>selection</a> changes to something different, and whenever a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>
of the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> at a given index in the <a href=#concept-selection title=concept-selection>selection</a> changes to something
different, the <a href=#state-override>state override</a> and <a href=#value-override>value override</a> must
be unset for every <a href=#command>command</a>.  The <a href=#value-override>value override</a> for
<a href=#the-backcolor-command>the <code title="">backColor</code> command</a> must be the same as the
<a href=#value-override>value override</a> for <a href=#the-hilitecolor-command>the <code title="">hiliteColor</code>
command</a>, such that setting one sets the other to the same thing and
unsetting one unsets the other.

<p class=note>The primary purpose of state and value overrides is that if the
user runs a command like <a href=#the-bold-command><code title="">bold</code></a>
with a collapsed selection, then types something without moving the cursor,
they expect it to have the given style (bold or such).  Thus the commands like
<a href=#the-bold-command><code title="">bold</code></a> set state and value
overrides, and <a href=#the-inserttext-command><code title="">insertText</code></a> checks for them and applies them to the
newly-inserted text.  Other commands like <a href=#the-delete-command><code title="">delete</code></a> also interact with overrides.

<p class=comments>See
<a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=16207">bug 16207</a>.

<p>When
<code class=external data-anolis-spec=html title=dom-Document-open><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#dom-document-open>document.open()</a></code> is
called and a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>'s singleton objects are all replaced by new instances
of those objects, editing state associated with that document (including the
<a href=#css-styling-flag>CSS styling flag</a>, <a href=#default-single-line-container-name>default single-line container name</a>,
and any <a href=#state-override title="state override">state overrides</a> or
<a href=#value-override title="value override">value overrides</a>) must be reset.

<p class=note>Of course, any action that replaces a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a> object
entirely, such as reloading the page, will also reset any editing state
associated with the document.

<p>When this specification refers to a method or attribute that is defined in a
specification, the user agent must treat the method or attribute as defined by
that specification.  In particular, if a script has overridden a standard
property with a custom one, the user agent must only use the overridden
property when a script refers to it, and must continue to use the
specification-defined behavior when this specification refers to it.

<p>When a list or set of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> is assigned to a variable without specifying
the order, they must be initially in <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a>, if they share a root.
(If they don't share a root, the order will be specified.)  When the user agent
is instructed to run particular steps for each member of a list, it must do so
sequentially in the list's order.


<h2 id=common-algorithms>Common algorithms</h2>

<h3 id=assorted-common-algorithms>Assorted common algorithms</h3>

<p>To move a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> to a new location, <dfn id=preserving-ranges>preserving ranges</dfn>, remove
the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> from its original <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> (if any), then insert it in the new
location.  In doing so, follow these rules instead of those defined by the
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-insert title=concept-node-insert>insert</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-remove title=concept-node-remove>remove</a> algorithms:

<p class=note>Many of the algorithms in this specification move nodes around in
the DOM.  The normal rules for range mutation require that any range endpoints
inside those nodes are moved to the node's parent as soon as the node is moved,
which would corrupt the selection.  For instance, if the user selects the text
"foo" and then bolds it, first we produce <code title="">&lt;b&gt;&lt;/b&gt;foo</code>, then <code title="">&lt;b&gt;foo&lt;/b&gt;</code>.  When
we move the "foo" text node into its new parent, we have to do so "preserving
ranges", so that the text "foo" is still selected.

<ol>
  <li>Let <var title="">node</var> be the moved <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, <var title="">old parent</var> and
  <var title="">old index</var> be the old <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> (which may be null) and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>,
  and <var title="">new parent</var> and <var title="">new index</var> be the new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> and
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>.

  <li>
  <p class=comments>This is actually implicit, but I state it anyway for
  completeness.

  <p>If a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> is the same as or a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of
  <var title="">node</var>, leave it unchanged, so it moves to the new location.

  <li>If a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> is <var title="">new parent</var> and its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a> is greater than <var title="">new index</var>, add one to its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>.

  <li>If a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> is <var title="">old parent</var> and its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a> is <var title="">old index</var> or <var title="">old index</var> + 1, set its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> to <var title="">new parent</var> and add <var title="">new index</var> &minus;
  <var title="">old index</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>.

  <li>If a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> is <var title="">old parent</var> and its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a> is greater than <var title="">old index</var> + 1, subtract one from its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>.
</ol>

<p class=comments>TODO: Do we want to get rid of attributes that are no longer
allowed here?

<p>To <dfn id=set-the-tag-name>set the tag name</dfn> of an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> <var title="">element</var> to
<var title="">new name</var>:

<p class=note>This is needed because the DOM doesn't allow any way of changing
an existing element's name.  Sometimes we want to, e.g., convert a markup
element to a span.  In that case we invoke this algorithm to create a new
element, move it to the right place, copy attributes from the old element, move
the old element's children, and remove the old element.

<ol>
  <li>If <var title="">element</var> is an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a>
  equal to <var title="">new name</var>, return <var title="">element</var>.

  <li>If <var title="">element</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is null, return <var title="">element</var>.

  <li>Let <var title="">replacement element</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">new name</var>)</a></code> on
  the <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">element</var>.

  <li>Insert <var title="">replacement element</var> into <var title="">element</var>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> immediately before <var title="">element</var>.

  <li>Copy all attributes of <var title="">element</var> to <var title="">replacement
  element</var>, in order.

  <li>While <var title="">element</var> has <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, append the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of
  <var title="">element</var> as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">replacement element</var>,
  <a href=#preserving-ranges>preserving ranges</a>.

  <li>Remove <var title="">element</var> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>Return <var title="">replacement element</var>.
</ol>

<p>To <dfn id=remove-extraneous-line-breaks-before>remove extraneous line breaks before</dfn> a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>
<var title="">node</var>:

<p class=note><code title="">&lt;br&gt;</code> sometimes has no effect in CSS, such
as in the markup <code title="">foo&lt;br&gt;&lt;p&gt;bar&lt;/p&gt;</code>.  In such cases
we like to remove the extra markup to keep things tidy.

<ol>
  <li>Let <var title="">ref</var> be the <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> of <var title="">node</var>.

  <li>If <var title="">ref</var> is null, abort these steps.

  <li>While <var title="">ref</var> has <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, set <var title="">ref</var> to its
  <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code>.

  <li>While <var title="">ref</var> is <a href=#invisible>invisible</a> but not an
  <a href=#extraneous-line-break>extraneous line break</a>, and <var title="">ref</var> does not equal
  <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>, set <var title="">ref</var> to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> before it in
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a>.

  <li>If <var title="">ref</var> is an <a href=#editable>editable</a> <a href=#extraneous-line-break>extraneous line
  break</a>, remove it from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
</ol>

<p>To <dfn id=remove-extraneous-line-breaks-at-the-end-of>remove extraneous line breaks at the end of</dfn> a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>
<var title="">node</var>:

<ol>
  <li>Let <var title="">ref</var> be <var title="">node</var>.

  <li>While <var title="">ref</var> has <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, set <var title="">ref</var> to its
  <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code>.

  <li>While <var title="">ref</var> is <a href=#invisible>invisible</a> but not an
  <a href=#extraneous-line-break>extraneous line break</a>, and <var title="">ref</var> does not equal
  <var title="">node</var>, set <var title="">ref</var> to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> before it in
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a>.

  <li>If <var title="">ref</var> is an <a href=#editable>editable</a> <a href=#extraneous-line-break>extraneous line
  break</a>:

  <ol>
    <li>
    <p class=comments>If the block ends with <code title="">&lt;span&gt;&lt;br&gt;&lt;/span&gt;</code>, for
    instance, we want to remove the span too.

    <p>While <var title="">ref</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#editable>editable</a> and
    <a href=#invisible>invisible</a>, set <var title="">ref</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Remove <var title="">ref</var> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
  </ol>
</ol>

<p>To <dfn id=remove-extraneous-line-breaks-from>remove extraneous line breaks from</dfn> a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, first
<a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a> it, then <a href=#remove-extraneous-line-breaks-at-the-end-of>remove
extraneous line breaks at the end of</a> it.


<h3 id=wrapping-a-list-of-nodes>Wrapping a list of nodes</h3>

<p>To <dfn id=wrap>wrap</dfn> a list <var title="">node list</var> of consecutive <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-sibling title=concept-tree-sibling>sibling</a>
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, run the following algorithm.  In addition to <var title="">node list</var>,
the algorithm accepts two inputs: an algorithm <var title="">sibling criteria</var> that
accepts a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> as input and outputs a boolean, and an algorithm <var title="">new
parent instructions</var> that accepts nothing as input and outputs a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>
or null.  If not provided, <var title="">sibling criteria</var> returns false and
<var title="">new parent instructions</var> returns null.

<p class=note>This algorithm basically does two things.  First, it looks at the
previous and next siblings of the nodes in <var title="">node list</var>.  If running
<var title="">sibling criteria</var> on one or both of the siblings returns true, the
nodes in <var title="">node list</var> are moved into the sibling(s).  Otherwise,
<var title="">new parent instructions</var> is run, and the result is used to wrap
<var title="">node list</var>.  For instance, to wrap <var title="">node list</var> in a <code title="">&lt;b&gt;</code>, one might invoke this algorithm with <var title="">sibling
criteria</var> returning true only for <code title="">&lt;b&gt;</code> elements and
<var title="">new parent instructions</var> creating and returning a new <code title="">&lt;b&gt;</code> element.

<ol>
  <li>
  <p class=comments>We need to treat <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>s as visible here even if they're
  not, because wrapping them might be significant even if they're invisible: it
  can turn an extraneous line break into a non-extraneous one.

  <p>If every member of <var title="">node list</var> is <a href=#invisible>invisible</a>, and
  none is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, return null and abort these steps.

  <li>If <var title="">node list</var>'s first member's <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is null, return null
  and abort these steps.

  <li>
  <p class=comments>Trailing br's like this always need to go along with their
  line.  Otherwise they'll create an extra line if we wrap in a block element,
  instead of vanishing as they should.

  <p>If <var title="">node list</var>'s last member is an <a href=#inline-node>inline node</a>
  that's not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, and <var title="">node list</var>'s last member's <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>
  is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, append that <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> to <var title="">node list</var>.

  <li>
  <p class=comments>See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13811">bug 13811</a>, <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14231">bug 14231</a>.  If
  there's a non-adjacent sibling that matches the sibling criteria and only
  invisible nodes intervene, we want to skip over the invisible nodes.  For
  instance, bolding <code title="">&lt;b&gt;foo&lt;/b&gt;&lt;!--bar--&gt;[baz]</code> should produce
  <code title="">&lt;b&gt;foo&lt;!--bar--&gt;baz&lt;/b&gt;</code>.  Similarly, and more usefully, creating an
  ordered list with <code title="">&lt;ol&gt;&lt;li&gt;foo&lt;/ol&gt; &lt;p&gt;[bar]&lt;/p&gt;</code> should produce
  <code title="">&lt;ol&gt;&lt;li&gt;foo&lt;/li&gt; &lt;li&gt;[bar]&lt;/ol&gt;</code>, not
  <code title="">&lt;ol&gt;&lt;li&gt;foo&lt;/ol&gt; &lt;ol&gt;&lt;li&gt;[bar]&lt;/ol&gt;</code>.

  <p>While <var title="">node list</var>'s first member's <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> is
  <a href=#invisible>invisible</a>, prepend it to <var title="">node list</var>.

  <li>While <var title="">node list</var>'s last member's <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is
  <a href=#invisible>invisible</a>, append it to <var title="">node list</var>.

  <li>If the <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> of the first member of <var title="">node list</var>
  is <a href=#editable>editable</a> and running <var title="">sibling criteria</var> on it
  returns true, let <var title="">new parent</var> be the <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> of the
  first member of <var title="">node list</var>.

  <li>Otherwise, if the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node
  list</var> is <a href=#editable>editable</a> and running <var title="">sibling criteria</var>
  on it returns true, let <var title="">new parent</var> be the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> of the
  last member of <var title="">node list</var>.

  <li>Otherwise, run <var title="">new parent instructions</var>, and let <var title="">new
  parent</var> be the result.

  <li>
  <p class=comments>This can only happen if <var title="">new parent instructions</var>
  is run and it returns null.  This can be used to only merge with adjacent
  siblings, in case you don't want to create a new parent if that fails.

  <p>If <var title="">new parent</var> is null, abort these steps and return null.

  <li><p class=comments>Most callers will create a new element to return in
  <var title="">new parent instructions</var>, whose parent will therefore be null.  But
  they can also return an existing node if that makes sense, so the nodes will
  be moved to an uncle or something.  The toggle lists algorithm makes use of
  this.

  <p>If <var title="">new parent</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is null:

  <ol>
    <li>Insert <var title="">new parent</var> into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of
    <var title="">node list</var> immediately before the first member of <var title="">node
    list</var>.

    <li>
    <div class=comments>
    <p>Basically, we want any boundary points around the wrapped nodes to go
    inside the wrapper.  Without this step, wrapping "{}&lt;br&gt;" in a blockquote
    would go like

    <pre>{}&lt;br&gt;
-&gt; {}&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br&gt;
-&gt; {}&lt;blockquote&gt;&lt;br&gt;&lt;/blockquote&gt;.</pre>

    <p>The second line is due to range mutation rules: a boundary point with an
    offset equal to the index of a newly-inserted node stays put, so it remains
    before it.  With this step, it goes like

    <pre>{}&lt;br&gt;
-&gt; {}&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br&gt;
-&gt; &lt;blockquote&gt;&lt;/blockquote&gt;{}&lt;br&gt;
-&gt; &lt;blockquote&gt;{}&lt;br&gt;&lt;/blockquote&gt;.</pre>

    <p>The difference in the final step is because we move the &lt;br&gt; "preserving
    ranges".  This means that adjacent boundary points get swept along with it.
    Previously, the &lt;blockquote&gt; intervened, so a boundary point after it would
    get taken along but one before it would not.

    <p>Another solution that one might be tempted to consider would be to just put
    the wrapper after the wrapped elements.  Then the boundary points would
    stay put, before the wrapper, so they'd still be adjacent to the nodes to
    be wrapped, like:

    <pre>{&lt;p&gt;foo&lt;/p&gt;}
-&gt; {&lt;p&gt;foo&lt;/p&gt;}&lt;blockquote&gt;&lt;/blockquote&gt;
-&gt; &lt;blockquote&gt;{&lt;p&gt;foo&lt;/p&gt;}&lt;/blockquote&gt;.</pre>

    <p>The problem is that this completely breaks if you're wrapping multiple
    things and not all are selected.  It would go like this:

    <pre>&lt;p&gt;foo&lt;/p&gt;{&lt;p&gt;bar&lt;/p&gt;}
-&gt; &lt;p&gt;foo&lt;/p&gt;{&lt;p&gt;bar&lt;/p&gt;}&lt;blockquote&gt;&lt;/blockquote&gt;
-&gt; &lt;p&gt;foo&lt;/p&gt;&lt;blockquote&gt;{&lt;p&gt;bar&lt;/p&gt;}&lt;/blockquote&gt;
-&gt; &lt;blockquote&gt;{&lt;p&gt;foo&lt;/p&gt;&lt;p&gt;bar&lt;/p&gt;}&lt;/blockquote&gt;.</pre>

    <p>The last step is again because of the range mutation rules: the boundary
    point stays put when a new node is inserted.  They're fundamentally
    asymmetric.

    <p>An alternative solution would be to define the concept of moving a list of
    adjacent sibling nodes while preserving ranges, and handle this explicitly
    at a more abstract level.

    <p>TODO: Think about this some more.  Maybe there's a better way.
    </div>

    <p>If any <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> equal to the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">new parent</var> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a> equal to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    of <var title="">new parent</var>, add one to that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>.
  </ol>

  <li>Let <var title="">original parent</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of
  <var title="">node list</var>.

  <li>If <var title="">new parent</var> is before the first member of <var title="">node
  list</var> in <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a>:

  <ol>
    <li>If <var title="">new parent</var> is not an <a href=#inline-node>inline node</a>, but the
    last <a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var> and the first
    <a href=#visible>visible</a> member of <var title="">node list</var> are both <a href=#inline-node title="inline node">inline nodes</a>, and the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new
    parent</var> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">new parent</var> and append the result as the
    last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var>.

    <li>For each <var title="">node</var> in <var title="">node list</var>, append
    <var title="">node</var> as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var>,
    <a href=#preserving-ranges>preserving ranges</a>.
  </ol>

  <li>Otherwise:

  <ol>
    <li>If <var title="">new parent</var> is not an <a href=#inline-node>inline node</a>, but the
    first <a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var> and the last
    <a href=#visible>visible</a> member of <var title="">node list</var> are both <a href=#inline-node title="inline node">inline nodes</a>, and the last member of <var title="">node
    list</var> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">new parent</var> and insert the result as the
    first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var>.

    <li>For each <var title="">node</var> in <var title="">node list</var>, <em>in reverse
    order</em>, insert <var title="">node</var> as the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new
    parent</var>, <a href=#preserving-ranges>preserving ranges</a>.
  </ol>

  <li>
  <p class=comments>This could happen if <var title="">new parent instructions</var>
  returned a node whose parent wasn't null.

  <p>If <var title="">original parent</var> is <a href=#editable>editable</a> and has no
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, remove it from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>
  <p class=comments>Probably because both the previous and next sibling met
  them.  We want to merge them in this case.

  <p>If <var title="">new parent</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is <a href=#editable>editable</a> and
  running <var title="">sibling criteria</var> on it returns true:

  <ol>
    <li>If <var title="">new parent</var> is not an <a href=#inline-node>inline node</a>, but
    <var title="">new parent</var>'s last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> and <var title="">new parent</var>'s
    <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>'s first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> are both <a href=#inline-node title="inline node">inline
    nodes</a>, and <var title="">new parent</var>'s last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>,
    call <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">new parent</var> and append the result as the
    last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var>.

    <li>While <var title="">new parent</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> has <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, append
    its first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new parent</var>,
    <a href=#preserving-ranges>preserving ranges</a>.

    <li>Remove <var title="">new parent</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
  </ol>

  <li><a href=#remove-extraneous-line-breaks-from>Remove extraneous line breaks from</a> <var title="">new parent</var>.

  <li>Return <var title="">new parent</var>.
</ol>


<h3 id=allowed-children>Allowed children</h3>

<div class=comments>
<p>List is mostly based on current HTML5, together with obsolete
elements.  I mostly got the obsolete element list by testing what Firefox 5.0a2
splits when you do insertHorizontalRule.

<p>TODO: The definitions of prohibited paragraph children and elements with
inline contents should be in the HTML spec (possibly under a different name) so
they don't fall out of sync.  They'll do for now.
</div>

<p>A <dfn id=name-of-an-element-with-inline-contents>name of an element with inline contents</dfn> is "a", "abbr", "b",
"bdi", "bdo", "cite", "code", "dfn", "em", "h1", "h2", "h3", "h4", "h5", "h6",
"i", "kbd", "mark", "p", "pre", "q", "rp", "rt", "ruby", "s", "samp", "small",
"span", "strong", "sub", "sup", "u", "var", "acronym", "listing", "strike",
"xmp", "big", "blink", "font", "marquee", "nobr", or "tt".

<p>An <dfn id=element-with-inline-contents>element with inline contents</dfn> is an <a href=#html-element>HTML element</a>
whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is a <a href=#name-of-an-element-with-inline-contents>name of an element with inline contents</a>.

<div class=comments>
<p>TODO: This list doesn't currently match HTML's validity requirements for a
few reasons:

<ol>
  <li>We need to handle invalid elements, which have no conformance
  requirements but should be treated properly.  In particular, they can
  interfere with serialization (e.g., center cannot descend from p).

  <li>Sometimes users give instructions that have to produce invalid DOMs to
  get the expected effect, like indenting the first item of a list.

  <li>The HTML validity requirements are sometimes quite complicated.

  <li>I just haven't had bothered to be systematic about it yet.  I've only
  covered what's come up in my tests.
</ol>

<p>I deliberately allow <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code> to contain headers and such, in violation of
HTML.  If I didn't, then when the user tried to formatBlock a <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code> as a
header, it would break apart the whole <code class=external data-anolis-spec=html title="the dl element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dl-element>dl</a></code>, which seems worse.  See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13201">bug 13201</a>.
</div>

<p>A <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> or string <var title="">child</var> is an <dfn id=allowed-child>allowed child</dfn> of a
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> or string <var title="">parent</var> if the following algorithm returns true:

<p class=note>Often we move around nodes, and sometimes this can result in
unreasonable things like two <code title="">&lt;p&gt;</code>'s nested inside one
another.  This algorithm checks for DOMs we never want to have, so that other
algorithms can avoid creating them or fix them if they do happen.  The
<a href=#fix-disallowed-ancestors>fix disallowed ancestors</a> algorithm is one frequently-invoked
caller of this algorithm.

<ol>
  <li>If <var title="">parent</var> is "colgroup", "table", "tbody", "tfoot", "thead",
  "tr", or an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> equal to one of
  those, and <var title="">child</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node whose <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> does not
  consist solely of <a class=external data-anolis-spec=encoding href=http://encoding.spec.whatwg.org/#ascii-whitespace title="ascii whitespace">space characters</a>, return false.

  <li>
  <p class=comments> Actually, no node can occur in the DOM after plaintext,
  generally.  But let's not get too carried away.

  <p>If <var title="">parent</var> is "script", "style", "plaintext", or "xmp", or an
  <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> equal to one of those, and
  <var title="">child</var> is not a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, return false.

  <li>If <var title="">child</var> is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>, <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#documentfragment>DocumentFragment</a></code>, or
  <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#documenttype>DocumentType</a></code>, return false.

  <li>If <var title="">child</var> is an <a href=#html-element>HTML element</a>, set <var title="">child</var>
  to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> of <var title="">child</var>.

  <li>If <var title="">child</var> is not a string, return true.

  <li>If <var title="">parent</var> is an <a href=#html-element>HTML element</a>:

  <ol>
    <li>
    <p class=comments>Cannot be serialized as text/html.  In some cases it can,
    like
    &lt;a&gt;foo&lt;table&gt;&lt;td&gt;&lt;a&gt;bar&lt;/a&gt;&lt;/td&gt;&lt;/table&gt;baz&lt;/a&gt;,
    but it's invalid in those cases too, so no need for complication.

    <p>If <var title="">child</var> is "a", and <var title="">parent</var> or some <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a>
    of <var title="">parent</var> is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code>, return false.

    <li>
    <p class=comments>This generally cannot be serialized either, for p.  For
    other elements with inline contents, this serves to prevent things like
    &lt;span&gt;&lt;p&gt;foo&lt;/p&gt;&lt;/span&gt;, which will parse fine but aren't
    supposed to happen anyway.

    <p>If <var title="">child</var> is a <a href=#prohibited-paragraph-child-name>prohibited paragraph child name</a>
    and <var title="">parent</var> or some <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">parent</var> is an
    <a href=#element-with-inline-contents>element with inline contents</a>, return false.

    <li>
    <p class=comments>Also can't be serialized as text/html.

    <p>If <var title="">child</var> is "h1", "h2", "h3", "h4", "h5", or "h6", and
    <var title="">parent</var> or some <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">parent</var> is an
    <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> "h1", "h2", "h3", "h4", "h5",
    or "h6", return false.

    <li>
    <p class=comments>Further requirements only care about the parent itself,
    not ancestors, so we don't need to know the node itself.

    <p>Let <var title="">parent</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> of <var title="">parent</var>.
  </ol>

  <li>If <var title="">parent</var> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> or <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#documentfragment>DocumentFragment</a></code>, return
  true.

  <li>If <var title="">parent</var> is not a string, return false.

  <li>
  <p class=comments>We allow children even where some intervening nodes will be
  inserted, like tr as a child of table.

  <p>If <var title="">parent</var> is on the left-hand side of an entry on the
  following list, then return true if <var title="">child</var> is listed on the
  right-hand side of that entry, and false otherwise.

  <ul>
    <li>colgroup: col
    <li>table: caption, col, colgroup, tbody, td, tfoot, th, thead, tr
    <li>tbody, tfoot, thead: td, th, tr
    <li>tr: td, th
    <li>dl: dt, dd
    <li>dir, ol, ul: dir, li, ol, ul
    <li>hgroup: h1, h2, h3, h4, h5, h6
  </ul>

  <li>If <var title="">child</var> is "body", "caption", "col", "colgroup", "frame",
  "frameset", "head", "html", "tbody", "td", "tfoot", "th", "thead", or "tr",
  return false.

  <li>
  <p class=comments>dd/dt/li will serialize fine as the child of random stuff,
  but it makes no sense at all, so we want to avoid it anyway.

  <p>If <var title="">child</var> is "dd" or "dt" and <var title="">parent</var> is not "dl",
  return false.

  <li>If <var title="">child</var> is "li" and <var title="">parent</var> is not "ol" or "ul",
  return false.

  <li>If <var title="">parent</var> is on the left-hand side of an entry on the
  following list and <var title="">child</var> is listed on the right-hand side of that
  entry, return false.

  <ul>
    <li>a: a
    <li>dd, dt: dd, dt
    <li>h1, h2, h3, h4, h5, h6: h1, h2, h3, h4, h5, h6
    <li>li: li
    <li>nobr: nobr
    <li>All <a href=#name-of-an-element-with-inline-contents title="name of an element with inline contents">names of an
    element with inline contents</a>: all <a href=#prohibited-paragraph-child-name title="prohibited
    paragraph child name">prohibited paragraph child names</a>
    <li>td, th: caption, col, colgroup, tbody, td, tfoot, th, thead, tr
  </ul>

  <li>Return true.
</ol>


<h2 id=inline-formatting-commands>Inline formatting commands</h2>

<h3 id=inline-formatting-command-definitions>Inline formatting command definitions</h3>

<p class=comments>The difference between "contained" and "effectively
contained" is basically that 1) in &lt;b&gt;[foo]&lt;/b&gt;, the text node and the
&lt;b&gt; are effectively contained but not contained; and 2) in
&lt;b&gt;f[o]o&lt;/b&gt;, the text node is effectively contained but not contained,
and the &lt;b&gt; is neither effectively contained nor contained.

<p>A <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> is <dfn id=effectively-contained>effectively contained</dfn> in a
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> <var title="">range</var> if <var title="">range</var> is not <code class=external data-anolis-spec=dom title=dom-Range-collapsed><a href=http://dom.spec.whatwg.org/#dom-range-collapsed>collapsed</a></code>, and
at least one of the following holds:

<ul>
  <li><var title="">node</var> is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">range</var>.

  <li>
  <p class=comments> So like &lt;b&gt;f[oo]&lt;/b&gt; or &lt;b&gt;f[o]o&lt;/b&gt; or
  &lt;b&gt;f[oo&lt;/b&gt;}, but not &lt;b&gt;foo[&lt;/b&gt;} or &lt;b&gt;f[]oo&lt;/b&gt;.

  <p><var title="">node</var> is <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, it is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code>
  node, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> is different from <var title="">range</var>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a>.

  <li><var title="">node</var> is <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>, it is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node,
  and <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-offset title=concept-range-end-offset>end offset</a> is not 0.

  <li>
  <p class=comments>Basically, anything whose children are all effectively
  contained should be effectively contained itself, except that in a case like
  &lt;b&gt;f[o]o&lt;/b&gt; we don't want &lt;b&gt; to be effectively contained even
  though the text node is.  That's because we split the text node before we
  actually do anything, and the &lt;b&gt; will no longer be effectively contained.

  <p><var title="">node</var> has at least one <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>; and all its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> are
  <a href=#effectively-contained>effectively contained</a> in <var title="">range</var>; and either
  <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is not a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">node</var>
  or is not a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node or <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is zero; and
  either <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a> is not a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of
  <var title="">node</var> or is not a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node or <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-offset title=concept-range-end-offset>end offset</a>
  is its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.
</ul>

<p>A <dfn id=modifiable-element>modifiable element</dfn> is a <code class=external data-anolis-spec=html title="the b element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-b-element>b</a></code>, <code class=external data-anolis-spec=html title="the em element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-em-element>em</a></code>, <code class=external data-anolis-spec=html title="the i element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-i-element>i</a></code>, <code class=external data-anolis-spec=html title="the s element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-s-element>s</a></code>, <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-span-element>span</a></code>,
<code class=external data-anolis-spec=html title="the strike element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#strike>strike</a></code>, <code class=external data-anolis-spec=html title="the strong element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-strong-element>strong</a></code>, <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sub</a></code>, <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sup</a></code>, or <code class=external data-anolis-spec=html title="the u element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-u-element>u</a></code> element with no attributes
except possibly <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code>; or a <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code> element with no attributes except
possibly <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code>, <code class=external data-anolis-spec=html title=dom-font-color><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-color>color</a></code>, <code class=external data-anolis-spec=html title=dom-font-face><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-face>face</a></code>, and/or <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-size>size</a></code>; or an
<code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> element with no attributes except possibly <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> and/or <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code>.

<p>A <dfn id=simple-modifiable-element>simple modifiable element</dfn> is an <a href=#html-element>HTML element</a> for
which at least one of the following holds:

<ul>
  <li>It is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code>, <code class=external data-anolis-spec=html title="the b element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-b-element>b</a></code>, <code class=external data-anolis-spec=html title="the em element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-em-element>em</a></code>, <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code>, <code class=external data-anolis-spec=html title="the i element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-i-element>i</a></code>, <code class=external data-anolis-spec=html title="the s element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-s-element>s</a></code>, <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-span-element>span</a></code>,
  <code class=external data-anolis-spec=html title="the strike element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#strike>strike</a></code>, <code class=external data-anolis-spec=html title="the strong element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-strong-element>strong</a></code>, <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sub</a></code>, <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sup</a></code>, or <code class=external data-anolis-spec=html title="the u element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-u-element>u</a></code> element with no
  attributes.

  <li>It is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code>, <code class=external data-anolis-spec=html title="the b element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-b-element>b</a></code>, <code class=external data-anolis-spec=html title="the em element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-em-element>em</a></code>, <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code>, <code class=external data-anolis-spec=html title="the i element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-i-element>i</a></code>, <code class=external data-anolis-spec=html title="the s element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-s-element>s</a></code>, <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-span-element>span</a></code>,
  <code class=external data-anolis-spec=html title="the strike element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#strike>strike</a></code>, <code class=external data-anolis-spec=html title="the strong element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-strong-element>strong</a></code>, <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sub</a></code>, <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sup</a></code>, or <code class=external data-anolis-spec=html title="the u element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-u-element>u</a></code> element with exactly one
  attribute, which is <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code>, which sets no CSS properties (including
  invalid or unrecognized properties).

  <li>It is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> element with exactly one attribute, which is <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code>.

  <li>It is a <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code> element with exactly one attribute, which is either
  <code class=external data-anolis-spec=html title=dom-font-color><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-color>color</a></code>, <code class=external data-anolis-spec=html title=dom-font-face><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-face>face</a></code>, or <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-size>size</a></code>.

  <li>It is a <code class=external data-anolis-spec=html title="the b element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-b-element>b</a></code> or <code class=external data-anolis-spec=html title="the strong element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-strong-element>strong</a></code> element with exactly one attribute, which is
  <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code>, and the <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute sets exactly one CSS property
  (including invalid or unrecognized properties), which is "font-weight".

  <li>It is an <code class=external data-anolis-spec=html title="the i element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-i-element>i</a></code> or <code class=external data-anolis-spec=html title="the em element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-em-element>em</a></code> element with exactly one attribute, which is
  <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code>, and the <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute sets exactly one CSS property
  (including invalid or unrecognized properties), which is "font-style".

  <li>It is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code>, <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code>, or <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-span-element>span</a></code> element with exactly one attribute,
  which is <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code>, and the <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute sets exactly one CSS property
  (including invalid or unrecognized properties), and that property is not
  "text-decoration".

  <li>It is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code>, <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code>, <code class=external data-anolis-spec=html title="the s element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-s-element>s</a></code>, <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-span-element>span</a></code>, <code class=external data-anolis-spec=html title="the strike element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#strike>strike</a></code>, or <code class=external data-anolis-spec=html title="the u element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-u-element>u</a></code> element
  with exactly one attribute, which is <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code>, and the <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute
  sets exactly one CSS property (including invalid or unrecognized properties),
  which is "text-decoration", which is set to "line-through" or "underline" or
  "overline" or "none".
</ul>

<p class=note>Conceptually, a simple modifiable element is a modifiable element
which specifies a value for at most one command.  As the names imply, inline
formatting commands will try not to modify anything other than modifiable
elements.  For instance, <code title="">&lt;dfn&gt;</code> normally creates italics,
but it's not modifiable, so running <a href=#the-italic-command>the <code title="">italic</code>
command</a> will not remove it: it will nest <code title="">&lt;span
style="font-style: normal"&gt;</code> inside.

<p>A <dfn id=formattable-node>formattable node</dfn> is an <a href=#editable>editable</a>
<a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is either a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, an <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#the-img-element>img</a></code>, or a
<code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>.

<p>Two quantities are <dfn id=equivalent-values>equivalent values</dfn> for a <a href=#command>command</a>
if either both are null, or both are strings and they're equal and the
<a href=#command>command</a> does not define any <a href=#equivalent-values>equivalent values</a>, or
both are strings and the <a href=#command>command</a> defines <a href=#equivalent-values>equivalent
values</a> and they match the definition.

<p>Two quantities are <dfn id=loosely-equivalent-values>loosely equivalent values</dfn> for a
<a href=#command>command</a> if either they are <a href=#equivalent-values>equivalent values</a> for the
<a href=#command>command</a>, or if the <a href=#command>command</a> is <a href=#the-fontsize-command>the <code title="">fontSize</code> command</a>; one of the quantities is one of
"x-small", "small", "medium", "large", "x-large", "xx-large", or "xxx-large";
and the other quantity is the <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> of "font-size" on a <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code> element
whose <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-size>size</a></code> attribute has the corresponding value set ("1" through "7"
respectively).

<p class=note>Loose equivalence needs to be used when comparing effective
command values to other values, while regular equivalence is used in other
cases.  The effective command value for fontSize is converted to pixels, so
comparing it to a specified value literally would produce false negatives.  But
a <em>specified</em> value in pixels is actually different from a
<em>specified</em> value like "small" or "x-large", because there is no precise
mapping from such keywords to pixels.

<p>If a <a href=#command>command</a> has <dfn id=inline-command-activated-values>inline command activated values</dfn>
defined but nothing else defines when it is <a href=#indeterminate>indeterminate</a>, it is
<a href=#indeterminate>indeterminate</a> if among <a href=#formattable-node title="formattable node">formattable
nodes</a> <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
range</a>, there is at least one whose <a href=#effective-command-value>effective command value</a>
is one of the given values and at least one whose <a href=#effective-command-value>effective command
value</a> is not one of the given values.

<p class=comments>For bold and similar commands, IE 9 RC seems to consider the
state true or false depending on the first element.  All other browsers follow
the same general idea as the spec, considering a range bold only if all text in
it is bold, and this seems to match at least OpenOffice.org's bold feature.
Opera 11.11 seemingly doesn't take CSS into account, and only looks at whether
something descends from a &lt;b&gt;.  I couldn't properly test IE9 because it
threw exceptions (Error: Unspecified error.) on most of the tests I ran.  But
what I have here seems to match Firefox 6.0a2 in every case, and Chrome 14 dev
in all cases with a few exceptions.

<p>If a <a href=#command>command</a> has <a href=#inline-command-activated-values>inline command activated values</a>
defined, its <a href=#state>state</a> is true if either no <a href=#formattable-node>formattable
node</a> is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
range</a>, and the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s
<a href=#effective-command-value>effective command value</a> is one of the given values; or if there is
at least one <a href=#formattable-node>formattable node</a> <a href=#effectively-contained>effectively contained</a>
in the <a href=#active-range>active range</a>, and all of them have an <a href=#effective-command-value>effective
command value</a> equal to one of the given values.

<div class=comments>
<p>Testing with hiliteColor: Opera 11.11 seems to always return the effective
command value of the active range's start node.  Chrome 14 dev returns boolean
false consistently, bizarrely enough.  Firefox 6.0a2 seems to follow the same
idea as the spec, but it likes to return "transparent", including sometimes
when the answer really clearly should not be "transparent".  IE9 throws
exceptions most of the time for backColor, so I can't say for sure, but in the
few cases where it doesn't throw it returns a random-looking number, so I'll
assume it's crazy like for foreColor.

<p>I decided on something that would guarantee the following invariant: whenever
you execute a command with a value provided (assuming value is relevant),
queryCommandValue() will always return something equivalent to what you set.
</div>

<p>If a command is a <dfn id=standard-inline-value-command>standard inline value command</dfn>, it is
<a href=#indeterminate>indeterminate</a> if among <a href=#formattable-node title="formattable node">formattable
nodes</a> that are <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
range</a>, there are two that have distinct <a href=#effective-command-value title="effective command
value">effective command values</a>.  Its <a href=#value>value</a> is the
<a href=#effective-command-value>effective command value</a> of the first <a href=#formattable-node>formattable node</a>
that is <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>; or
if there is no such node, the <a href=#effective-command-value>effective command value</a> of the
<a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>; or if that is null, the empty
string.

<p class=note>The notions of inline command activated values and standard
inline value commands are mostly just shorthand to avoid repeating the same
boilerplate half a dozen times.


<h3 id=assorted-inline-formatting-command-algorithms>Assorted inline formatting command algorithms</h3>

<p>The <dfn id=effective-command-value>effective command value</dfn> of a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> for a
given <var title="">command</var> is returned by the following algorithm, which will
return either a string or null:

<p class=note>This is logically somewhat like CSS computed or resolved values,
and in fact for most commands it's identical to CSS resolved values (see the
end of the algorithm).  We need a separate concept for some commands where we
can't rely on CSS for some reason: createLink and unlink aren't CSS-related at
all, backColor and hiliteColor need special treatment because background-color
isn't an inherited property, subscript and superscript rely on <code title="">&lt;sub&gt;</code>/<code title="">&lt;sup&gt;</code> instead of CSS
vertical-align, and strikethrough and underline don't map to unique CSS
properties.

<ol>
  <li>If neither <var title="">node</var> nor its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, return
  null.

  <li>If <var title="">node</var> is not an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, return the <a href=#effective-command-value>effective
  command value</a> of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> for <var title="">command</var>.

  <li>If <var title="">command</var> is "createLink" or "unlink":

  <ol>
    <li>While <var title="">node</var> is not null, and is not an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> element that has
    an <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code> attribute, set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>If <var title="">node</var> is null, return null.

    <li>Return the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-attribute-value title=concept-attribute-value>value</a> of <var title="">node</var>'s <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code> attribute.
  </ol>

  <li>If <var title="">command</var> is "backColor" or "hiliteColor":

  <ol>
    <li>While the <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> of "background-color" on <var title="">node</var> is
    any fully transparent value, and <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an
    <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>
    <div class=comments>
    <p>What happens if everything's background is fully transparent?  See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14068">bug</a>.  If you
    do queryCommandValue() for backColor/hiliteColor when no backgrounds are
    set anywhere, so it goes up to the root element, no two engines agree.
    IE10PP2 just returns a random-looking number (16777215).  Firefox 8.0a2
    returns "transparent", Chrome 15 dev returns "rgba(0, 0, 0, 0)", and Opera
    11.50 returns "rgb(255, 255, 255)".

    <p>Opera's behavior is incorrect.  The current page might be an iframe, in
    which case the background really will be transparent and the (inaccessible)
    background color of the parent page will show through.  Also, the user
    might have changed their preferences, but I'm not too worried about that.

    <p>So instead we just return the value as-is.  This means that it will be
    fully transparent, which is perhaps somewhat useless information, but it's
    the best we can do.  More generally, any non-opaque value is not going to
    tell you what you actually want, namely "what color is the user actually
    seeing?"  We have no realistic way to work around this in the general case.
    </div>

    <p>Return the <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> of "background-color" for <var title="">node</var>.
  </ol>

  <li>If <var title="">command</var> is "subscript" or "superscript":

  <ol>
    <li>Let <var title="">affected by subscript</var> and <var title="">affected by
    superscript</var> be two boolean variables, both initially false.

    <li>While <var title="">node</var> is an <a href=#inline-node>inline node</a>:

    <ol>
      <li>
      <p class=comments>Firefox 6.0a2 ignores vertical-align for this purpose,
      and only cares about &lt;sub&gt; and &lt;sup&gt; tags themselves.  Opera 11.11
      is similar, and in fact behaves like that even for commands like bold.
      The spec originally followed Chrome 14 dev, mainly because WebKit itself
      will produce spans with vertical-align sub or super, and we want to
      handle them correctly.  However, Ryosuke <a href=https://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-August/032809.html>informs</a>
      me that WebKit's behavior here is viewed as <a href="https://bugs.webkit.org/show_bug.cgi?id=11089">a bug</a>, so I
      changed it to match Gecko/Opera.

      <p>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sub</a></code>, set <var title="">affected by subscript</var>
      to true.

      <li>Otherwise, if <var title="">node</var> is a <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sup</a></code>, set <var title="">affected by
      superscript</var> to true.

      <li>Set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
    </ol>

    <li>If <var title="">affected by subscript</var> and <var title="">affected by
    superscript</var> are both true, return the string "mixed".

    <li>If <var title="">affected by subscript</var> is true, return "subscript".

    <li>If <var title="">affected by superscript</var> is true, return "superscript".

    <li>Return null.
  </ol>

  <li>If <var title="">command</var> is "strikethrough", and the "text-decoration"
  property of <var title="">node</var> or any of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> has <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a>
  containing "line-through", return "line-through".  Otherwise, return null.

  <li>If <var title="">command</var> is "underline", and the "text-decoration"
  property of <var title="">node</var> or any of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> has <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a>
  containing "underline", return "underline".  Otherwise, return null.

  <li>Return the <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> for <var title="">node</var> of the <a href=#relevant-css-property>relevant CSS
  property</a> for <var title="">command</var>.
</ol>

<p>The <dfn id=specified-command-value>specified command value</dfn> of an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> <var title="">element</var>
for a given <var title="">command</var> is returned by the following algorithm, which
will return either a string or null:

<p class=note>This is logically somewhat like CSS inline style.  In addition to
the caveats for effective command value, we also treat elements like <code title="">&lt;b&gt;</code> and <code title="">&lt;font&gt;</code> as having the same meaning
as <code title="">&lt;span&gt;</code>s with inline style set, because they're
logically pretty much the same and can in fact be produced by the same command
depending on the <a href=#css-styling-flag>CSS styling flag</a>.

<ol>
  <li>If <var title="">command</var> is "backColor" or "hiliteColor" and the
  <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>'s display property does not have <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> "inline", return
  null.

  <li>If <var title="">command</var> is "createLink" or "unlink":

  <ol>
    <li>If <var title="">element</var> is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> element and has an <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code>
    attribute, return the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-attribute-value title=concept-attribute-value>value</a> of that attribute.

    <li>Return null.
  </ol>

  <li>If <var title="">command</var> is "subscript" or "superscript":

  <ol>
    <li>If <var title="">element</var> is a <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sup</a></code>, return "superscript".

    <li>If <var title="">element</var> is a <code class=external data-anolis-spec=html title="the sub and sup elements"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-sub-and-sup-elements>sub</a></code>, return "subscript".

    <li>Return null.
  </ol>

  <li>If <var title="">command</var> is "strikethrough", and <var title="">element</var> has a
  <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute set, and that attribute sets "text-decoration":

  <ol>
    <li>If <var title="">element</var>'s <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute sets "text-decoration" to a
    value containing "line-through", return "line-through".

    <li>Return null.
  </ol>

  <li>If <var title="">command</var> is "strikethrough" and <var title="">element</var> is an
  <code class=external data-anolis-spec=html title="the s element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-s-element>s</a></code> or <code class=external data-anolis-spec=html title="the strike element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#strike>strike</a></code> element, return "line-through".

  <li>If <var title="">command</var> is "underline", and <var title="">element</var> has a
  <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute set, and that attribute sets "text-decoration":

  <ol>
    <li>If <var title="">element</var>'s <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute sets "text-decoration" to a
    value containing "underline", return "underline".

    <li>Return null.
  </ol>

  <li>If <var title="">command</var> is "underline" and <var title="">element</var> is a <code class=external data-anolis-spec=html title="the u element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-u-element>u</a></code>
  element, return "underline".

  <li>Let <var title="">property</var> be the <a href=#relevant-css-property>relevant CSS property</a> for
  <var title="">command</var>.

  <li>If <var title="">property</var> is null, return null.

  <li>If <var title="">element</var> has a <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute set, and that attribute has
  the effect of setting <var title="">property</var>, return the value that it sets
  <var title="">property</var> to.

  <li>If <var title="">element</var> is a <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code> element that has an attribute whose
  effect is to create a <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#presentational-hints title="presentational hints">presentational hint</a> for <var title="">property</var>, return
  the value that the hint sets <var title="">property</var> to.  (For a <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-size>size</a></code> of
  7, this will be the non-CSS value "xxx-large".)

  <li>If <var title="">element</var> is in the following list, and <var title="">property</var> is
  equal to the CSS property name listed for it, return the string listed for
  it.

  <ul>
    <li><code class=external data-anolis-spec=html title="the b element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-b-element>b</a></code>, <code class=external data-anolis-spec=html title="the strong element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-strong-element>strong</a></code>: font-weight: "bold"

    <li><code class=external data-anolis-spec=html title="the i element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-i-element>i</a></code>, <code class=external data-anolis-spec=html title="the em element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-em-element>em</a></code>: font-style: "italic"
  </ul>

  <li>Return null.
</ol>

<p>To <dfn id=record-the-values>record the values</dfn> of a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> <var title="">node list</var>:

<p class=note>When we move nodes around, we often change their parents.  If
their parents had any styles applied, this will make the nodes' styles change
too, which often isn't what we want.  For instance, if something is wrapped in
<code title="">&lt;blockquote style="color: red"&gt;</code>, and a script runs
<a href=#the-outdent-command>the <code title="">outdent</code> command</a> on it, the blockquote will
be removed and the style will go along with it.  Recording the values of its
children first, then restoring them afterward, will ensure the nodes don't
change color when outdented.

<ol>
  <li>Let <var title="">values</var> be a list of (<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, <a href=#command>command</a>,
  <a href=#specified-command-value>specified command value</a>) triples, initially empty.

  <li>
  <p class=comments>As with removeFormat, we put subscript first so it doesn't
  interfere with fontSize, and omit superscript because it's redundant with
  subscript.

  <p>For each <var title="">node</var> in <var title="">node list</var>, for each
  <var title="">command</var> in the list "subscript", "bold", "fontName", "fontSize",
  "foreColor", "hiliteColor", "italic", "strikethrough", and "underline" in
  that order:

  <ol>
    <li>Let <var title="">ancestor</var> equal <var title="">node</var>.

    <li>If <var title="">ancestor</var> is not an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, set it to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>While <var title="">ancestor</var> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> and its <a href=#specified-command-value>specified
    command value</a> for <var title="">command</var> is null, set it to its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>If <var title="">ancestor</var> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, add (<var title="">node</var>,
    <var title="">command</var>, <var title="">ancestor</var>'s <a href=#specified-command-value>specified command
    value</a> for <var title="">command</var>) to <var title="">values</var>.  Otherwise add
    (<var title="">node</var>, <var title="">command</var>, null) to <var title="">values</var>.
  </ol>

  <li>Return <var title="">values</var>.
</ol>

<p>To <dfn id=restore-the-values>restore the values</dfn> specified by a list <var title="">values</var>
returned by the <a href=#record-the-values>record the values</a> algorithm:

<ol>
  <li>For each (<var title="">node</var>, <var title="">command</var>, <var title="">value</var>) triple
  in <var title="">values</var>:

  <ol>
    <li>Let <var title="">ancestor</var> equal <var title="">node</var>.

    <li>If <var title="">ancestor</var> is not an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, set it to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>While <var title="">ancestor</var> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> and its <a href=#specified-command-value>specified
    command value</a> for <var title="">command</var> is null, set it to its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>If <var title="">value</var> is null and <var title="">ancestor</var> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>,
    <a href=#push-down-values>push down values</a> on <var title="">node</var> for <var title="">command</var>,
    with <var title="">new value</var> null.

    <li>Otherwise, if <var title="">ancestor</var> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> and its
    <a href=#specified-command-value>specified command value</a> for <var title="">command</var> is not <a href=#equivalent-values title="equivalent values">equivalent</a> to <var title="">value</var>, or if
    <var title="">ancestor</var> is not an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> and <var title="">value</var> is not null,
    <a href=#force-the-value>force the value</a> of <var title="">command</var> to <var title="">value</var> on
    <var title="">node</var>.
  </ol>
</ol>



<h3 id="clearing-an-element's-value">Clearing an element's value</h3>

<p>To <dfn id=clear-the-value>clear the value</dfn> of an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> <var title="">element</var>:

<p class=note>The idea is to remove any <a href=#specified-command-value>specified command value</a>
that the element might have for the command.  This might involve changing its
attributes, <a href=#set-the-tag-name title="set the tag name">setting its tag name</a>, or
removing it entirely while leaving its children in place.  The key caller is
<a href="#set-the-selection's-value">set the selection's value</a>, which clears the values of everything
in the selection before doing anything else to keep the markup tidy.

<ol>
  <li>Let <var title="">command</var> be the current <a href=#command>command</a>.

  <li>If <var title="">element</var> is not <a href=#editable>editable</a>, return the empty
  list.

  <li>
  <p class=comments>We want to abort early so that we don't try unsetting
  background-color on a non-inline element.

  <p>If <var title="">element</var>'s <a href=#specified-command-value>specified command value</a> for
  <var title="">command</var> is null, return the empty list.

  <li>If <var title="">element</var> is a <a href=#simple-modifiable-element>simple modifiable element</a>:

  <ol>
    <li>Let <var title="">children</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> of <var title="">element</var>.

    <li>For each <var title="">child</var> in <var title="">children</var>, insert
    <var title="">child</var> into <var title="">element</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> immediately before
    <var title="">element</var>, <a href=#preserving-ranges>preserving ranges</a>.

    <li>Remove <var title="">element</var> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Return <var title="">children</var>.
  </ol>

  <li>If <var title="">command</var> is "strikethrough", and <var title="">element</var> has a
  <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute that sets "text-decoration" to some value containing
  "line-through", delete "line-through" from the value.

  <li>If <var title="">command</var> is "underline", and <var title="">element</var> has a
  <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute that sets "text-decoration" to some value containing
  "underline", delete "underline" from the value.

  <li>If the <a href=#relevant-css-property>relevant CSS property</a> for <var title="">command</var> is not
  null, unset that property of <var title="">element</var>.

  <li>If <var title="">element</var> is a <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code> element:

  <ol>
    <li>If <var title="">command</var> is "foreColor", unset <var title="">element</var>'s
    <code class=external data-anolis-spec=html title=dom-font-color><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-color>color</a></code> attribute, if set.

    <li>If <var title="">command</var> is "fontName", unset <var title="">element</var>'s
    <code class=external data-anolis-spec=html title=dom-font-face><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-face>face</a></code> attribute, if set.

    <li>If <var title="">command</var> is "fontSize", unset <var title="">element</var>'s
    <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-size>size</a></code> attribute, if set.
  </ol>

  <li>If <var title="">element</var> is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> element and <var title="">command</var> is
  "createLink" or "unlink", unset the <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code> property of <var title="">element</var>.

  <li>
  <p class=comments>If we get past this step, we're something like &lt;b
  class=foo&gt; where we want to keep the extra attributes, so we stick them on a
  span.

  <p>If <var title="">element</var>'s <a href=#specified-command-value>specified command value</a> for
  <var title="">command</var> is null, return the empty list.

  <li><a href=#set-the-tag-name>Set the tag name</a> of <var title="">element</var> to "span", and return
  the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of the result.
</ol>


<h3 id=pushing-down-values>Pushing down values</h3>

<div class=comments>
<p>This algorithm goes up to just below the nearest ancestor with the right
style, then re-applies the bad styles repeatedly going down, omitting the
things we want to have the new style.  This is basically what WebKit does,
although WebKit sometimes starts higher up and therefore makes more intrusive
changes, often creating more markup.  IE follows the same general approach too.

<p>Gecko instead seems to start breaking up elements from the bottom, so that the
range consists of a few consecutive siblings, and it can then break up the
problematic element into a maximum of two pieces.  The spec's approach seems to
create fewer elements and simpler markup (or at least markup that's no more
complex) in most cases I throw at it.

<p>Gecko's approach does have the major advantage that it gets underlines right in
many cases for free.  E.g.,

<pre>&lt;u&gt;foo&lt;font color=red&gt;[bar]baz&lt;/font&gt;&lt;/u&gt;
-&gt; &lt;u&gt;foo&lt;/u&gt;&lt;font color=red&gt;bar&lt;u&gt;baz&lt;/u&gt;&lt;/font&gt; (spec)
-&gt; &lt;u&gt;foo&lt;/u&gt;&lt;font color=red&gt;bar&lt;/font&gt;&lt;u&gt;&lt;font color=red&gt;baz&lt;/font&gt;&lt;/u&gt; (Gecko)</pre>

<p>The spec's markup here is much shorter and contains fewer elements, but is
wrong: the underline under "baz" has changed color from black to red.  It might
be worth trying to copy Gecko's results in such cases, but that won't solve all
underline problems, so perhaps it's not worth it.

<p>Opera also seems to break up the markup surrounding the range, but even more
aggressively: even if it doesn't need to pull down styles.  In some cases this
does actually result in shorter markup, specifically if the existing tags are
short (like i or b) and we're adding tags that are long (like span with a style
attribute).
</div>

<p>To <dfn id=push-down-values>push down values</dfn> to a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var>, given a new
value <var title="">new value</var>:

<p class=note>The idea here is that if an undesired value is being propagated
from an ancestor, we remove that style from the ancestor and re-apply it to all
the descendants other than <var title="">node</var>.  This way we don't have to have
nested styles, which is usually more cluttered (although not always).

<ol>
  <li>Let <var title="">command</var> be the current <a href=#command>command</a>.

  <li>
  <p class=comments>E.g., a text node child of a document fragment.

  <p>If <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, abort this
  algorithm.

  <li>If the <a href=#effective-command-value>effective command value</a> of <var title="">command</var> is
  <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">new value</var> on <var title="">node</var>, abort this
  algorithm.

  <li>Let <var title="">current ancestor</var> be <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>Let <var title="">ancestor list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

  <li>While <var title="">current ancestor</var> is an <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>
  and the <a href=#effective-command-value>effective command value</a> of <var title="">command</var> is not
  <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">new value</var> on it, append <var title="">current
  ancestor</var> to <var title="">ancestor list</var>, then set <var title="">current
  ancestor</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If <var title="">ancestor list</var> is empty, abort this algorithm.

  <li>Let <var title="">propagated value</var> be the <a href=#specified-command-value>specified command
  value</a> of <var title="">command</var> on the last member of <var title="">ancestor
  list</var>.

  <li>
  <p class=comments>We can only remove specified values, so if the value isn't
  specified, give up.  Unless we're actually trying to push down a null
  specified value, like for unlink.

  <p>If <var title="">propagated value</var> is null and is not equal to <var title="">new
  value</var>, abort this algorithm.

  <li>
  <div class=comments>
  <p>If we go all the way up to the root and still don't have the desired value,
  pushing down values is pointless.  It will create extra markup for no
  purpose.  Except if the value is null, which basically just means "try to get
  rid of anything affecting the current element but don't aim for any specific
  value".

  <p>Nevertheless, Chrome 14 dev does seem to do this.  Running bold on
  &lt;span style=font-weight:300&gt;f[o]o&lt;/span&gt; breaks up the span and adds a
  &lt;b&gt; as a sibling.  In IE9, Firefox 6.0a2, and Opera 11.50, it instead
  nests the &lt;b&gt; inside the &lt;span&gt;.  It's a tradeoff: WebKit's behavior is
  better for things like

<pre>&lt;font color=red&gt;fo[o&lt;/font&gt;&lt;font color=blue&gt;b]ar&lt;/font&gt;
-&gt; &lt;font color=red&gt;fo&lt;/font&gt;&lt;font color=green&gt;[ob]&lt;/font&gt;&lt;font color=blue&gt;ar&lt;/font&gt;</pre>

  <p>(where the spec adds two extra font tags instead of one), but the spec is
  simpler for things like

<pre>&lt;font color=red&gt;f[o]o&lt;/font&gt;
-&gt; &lt;font color=red&gt;f&lt;font color=green&gt;[o]&lt;/font&gt;o&lt;/font&gt;</pre>

  <p>(where WebKit splits the existing tag up in addition to creating a new tag).
  I'm not particularly sure which approach is better overall, so I'll go with
  the majority of browsers.  If these algorithms move to use runs of
  consecutive siblings instead of doing everything node-by-node, it might make
  sense to break up the parent as long as it won't create an extra node (i.e.,
  we're styling something that includes the first or last child).
  </div>

  <p>If the <a href=#effective-command-value>effective command value</a> of <var title="">command</var> is not
  <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">new value</var> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of the last
  member of <var title="">ancestor list</var>, and <var title="">new value</var> is not null,
  abort this algorithm.

  <li>While <var title="">ancestor list</var> is not empty:

  <ol>
    <li>Let <var title="">current ancestor</var> be the last member of <var title="">ancestor
    list</var>.

    <li>Remove the last member from <var title="">ancestor list</var>.

    <li>If the <a href=#specified-command-value>specified command value</a> of <var title="">current
    ancestor</var> for <var title="">command</var> is not null, set <var title="">propagated
    value</var> to that value.

    <li>Let <var title="">children</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> of <var title="">current
    ancestor</var>.

    <li>If the <a href=#specified-command-value>specified command value</a> of <var title="">current
    ancestor</var> for <var title="">command</var> is not null, <a href=#clear-the-value>clear the
    value</a> of <var title="">current ancestor</var>.

    <li>For every <var title="">child</var> in <var title="">children</var>:

    <ol>
      <li>If <var title="">child</var> is <var title="">node</var>, continue with the next
      <var title="">child</var>.

      <li>
      <p class=comments> TODO: This will be incorrect for relative font sizes.
      If the font size on the parent was removed and the font size on the child
      is in ems or percents or something, it will now change value.  This isn't
      likely to come up, so we'll ignore it for now.

      <p>If <var title="">child</var> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> whose <a href=#specified-command-value>specified command
      value</a> for <var title="">command</var> is neither null nor <a href=#equivalent-values title="equivalent values">equivalent</a> to <var title="">propagated
      value</var>, continue with the next <var title="">child</var>.

      <li>If <var title="">child</var> is the last member of <var title="">ancestor list</var>,
      continue with the next <var title="">child</var>.

      <li><a href=#force-the-value>Force the value</a> of <var title="">child</var>, with
      <var title="">command</var> as in this algorithm and <var title="">new value</var> equal
      to <var title="">propagated value</var>.
    </ol>
  </ol>
</ol>


<h3 id=forcing-the-value-of-a-node>Forcing the value of a node</h3>

<p>To <dfn id=force-the-value>force the value</dfn> of a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> to <var title="">new
value</var>:

<p class=note>This algorithm checks if the node has the desired value, and if
not, it wraps the node (or, if that's not possible, its descendants) in a
<a href=#simple-modifiable-element>simple modifiable element</a>.  After forcing the value, descendants
might still have a different value.

<ol>
  <li>Let <var title="">command</var> be the current <a href=#command>command</a>.

  <li>If <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is null, abort this algorithm.

  <li>If <var title="">new value</var> is null, abort this algorithm.

  <li>If <var title="">node</var> is an <a href=#allowed-child>allowed child</a> of "span":

  <ol>
    <li>
    <div class=comments>
    <p>Even if the value matches, we stick it in a preceding sibling if
    possible.  This ensures "a&lt;cite&gt;b&lt;/cite&gt;c" -&gt;
    "&lt;i&gt;a&lt;cite&gt;b&lt;/cite&gt;c&lt;/i&gt;" instead of
    "&lt;i&gt;a&lt;/i&gt;&lt;cite&gt;b&lt;/cite&gt;&lt;i&gt;c&lt;/i&gt;".  While we're at it, we
    also handle more elaborate cases like &lt;b&gt;foo&lt;/b&gt;[bar]&lt;b&gt;baz&lt;/b&gt;
    and even &lt;i&gt;&lt;b&gt;foo&lt;/b&gt;&lt;/i&gt;[bar]&lt;i&gt;&lt;b&gt;baz&lt;/b&gt;&lt;/i&gt;
    (the latter becomes &lt;b&gt;&lt;i&gt;foo&lt;/i&gt;bar&lt;i&gt;baz&lt;/i&gt;&lt;/b&gt;).

    <p>Theoretically this algorithm could pointlessly reorganize the DOM in the
    event of unreasonable style rules, but it's not a big enough deal for us to
    care, since the resulting style will still be right.
    </div>

    <p><a href=#reorder-modifiable-descendants>Reorder modifiable descendants</a> of <var title="">node</var>'s
    <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code>.

    <li><a href=#reorder-modifiable-descendants>Reorder modifiable descendants</a> of <var title="">node</var>'s
    <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>.

    <li>
    <p class=comments>The <var title="">new parent instructions</var> we'd want are too
    complicated to reasonably feed into the wrap algorithm, so we just let them
    return null and do the wrapping ourselves if <var title="">sibling criteria</var>
    didn't return true.

    <p><a href=#wrap>Wrap</a> the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of <var title="">node</var>,
    with <var title="">sibling criteria</var> returning true for a <a href=#simple-modifiable-element>simple
    modifiable element</a> whose <a href=#specified-command-value>specified command value</a> is
    <a href=#equivalent-values title="equivalent values">equivalent</a> to <var title="">new value</var> and whose <a href=#effective-command-value>effective command
    value</a> is <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">new value</var> and false
    otherwise, and with <var title="">new parent instructions</var> returning null.
  </ol>

  <li>
  <p class=comments><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13996">Bug 13996</a>.

  <p>If <var title="">node</var> is <a href=#invisible>invisible</a>, abort this algorithm.

  <li>If the <a href=#effective-command-value>effective command value</a> of <var title="">command</var> is
  <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">new value</var> on <var title="">node</var>, abort this
  algorithm.

  <li>If <var title="">node</var> is not an <a href=#allowed-child>allowed child</a> of "span":

  <ol>
    <li>Let <var title="">children</var> be all <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> of <var title="">node</var>,
    omitting any that are <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>s whose <a href=#specified-command-value>specified command
    value</a> for <var title="">command</var> is neither null nor <a href=#equivalent-values title="equivalent values">equivalent</a> to <var title="">new value</var>.

    <li>
    <p class=comments>This means that if it has no children, we do nothing.
    IE9 inserts an empty wrapper element in that case, but I'm not sure what
    the point is, and no one else does, so I don't.  WebKit seems to ignore the
    node if its only child consists solely of whitespace, but I don't see any
    grounds for that and no one else does, so I don't.

    <p><a href=#force-the-value>Force the value</a> of each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> in <var title="">children</var>,
    with <var title="">command</var> and <var title="">new value</var> as in this invocation of
    the algorithm.

    <li>Abort this algorithm.
  </ol>

  <li>If the <a href=#effective-command-value>effective command value</a> of <var title="">command</var> is
  <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">new value</var> on <var title="">node</var>, abort this
  algorithm.

  <li>Let <var title="">new parent</var> be null.

  <li>If the <a href=#css-styling-flag>CSS styling flag</a> is false:

  <ol>
    <li>If <var title="">command</var> is "bold" and <var title="">new value</var> is
    "bold", let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("b")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.

    <li>If <var title="">command</var> is "italic" and <var title="">new value</var> is
    "italic", let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("i")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.

    <li>
    <p class=comments>TODO: Actual UAs use strike, not s, but s is shorter and
    HTML5 makes strike invalid.  I've gone with s for now, but maybe we want to
    change the spec to require strike.

    <p>If <var title="">command</var> is "strikethrough" and <var title="">new value</var> is
    "line-through", let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("s")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.

    <li>If <var title="">command</var> is "underline" and <var title="">new value</var> is
    "underline", let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("u")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.

    <li>
    <p class=comments>See comment for foreColor for discussion.  TODO: Define
    more carefully what happens when things are out of range or not integers or
    whatever.

    <p>If <var title="">command</var> is "foreColor", and <var title="">new value</var> is fully
    opaque with red, green, and blue components in the range 0 to 255:

    <ol>
      <li>Let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("font")</a></code> on the
      <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.

      <li>Set the <code class=external data-anolis-spec=html title=dom-font-color><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-color>color</a></code> attribute of <var title="">new parent</var> to the
      result of applying the <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#rules-for-serializing-simple-color-values>rules for serializing
      simple color values</a> to <var title="">new value</var> (interpreted as a
      <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#simple-color>simple color</a>).
    </ol>

    <li>If <var title="">command</var> is "fontName", let <var title="">new parent</var> be
    the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("font")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>, then set the <code class=external data-anolis-spec=html title=dom-font-face><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-face>face</a></code> attribute
    of <var title="">new parent</var> to <var title="">new value</var>.
  </ol>

  <li>If <var title="">command</var> is "createLink" or "unlink":

  <ol>
    <li>Let <var title="">new parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("a")</a></code> on the
    <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.

    <li>Set the <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code> attribute of <var title="">new parent</var> to <var title="">new
    value</var>.

    <li>
    <p class=comments>Nested a elements are bad, because they can't be
    serialized to text/html.  hrefs should already have been cleared in a
    previous step, but we might have &lt;a name&gt; or such lurking about.

    <p>Let <var title="">ancestor</var> be <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>While <var title="">ancestor</var> is not null:

    <ol>
      <li>
      <p class=comments> TODO: This will mean any link-specific attributes will
      be transferred, which makes them both invalid and useless.  Is that okay?
      I don't really want to list them all, because that sort of list is prone
      to bitrot.

      <p>If <var title="">ancestor</var> is an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code>, <a href=#set-the-tag-name>set the tag name</a> of
      <var title="">ancestor</var> to "span", and let <var title="">ancestor</var> be the
      result.

      <li>Set <var title="">ancestor</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
    </ol>
  </ol>

  <li>
  <p class=comments>WebKit is the only engine that ever outputs anything but
  font tags for fontSize.  For size=7, it uses font-size: -webkit-xxx-large.
  We just output a font tag no matter what for size=7.

  <p>If <var title="">command</var> is "fontSize"; and <var title="">new value</var> is one of
  "x-small", "small", "medium", "large", "x-large", "xx-large", or
  "xxx-large"; and either the <a href=#css-styling-flag>CSS styling flag</a> is false, or
  <var title="">new value</var> is "xxx-large": let <var title="">new parent</var> be the result
  of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("font")</a></code> on the
  <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>, then set the <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-size>size</a></code> attribute of
  <var title="">new parent</var> to the number from the following table based on
  <var title="">new value</var>:

  <ul>
    <li>x-small: 1
    <li>small: 2
    <li>normal: 3
    <li>large: 4
    <li>x-large: 5
    <li>xx-large: 6
    <li>xxx-large: 7
  </ul>

  <li>
  <p class=comments>We always use sup/sub elements, even in CSS mode, following
  Gecko and contradicting WebKit.  This is because &lt;span
  value="vertical-align: sub/super"&gt;, the obvious equivalent (and what WebKit
  uses), behaves quite differently: it doesn't reduce font-size, which is ugly.
  WebKit's behavior is <a href="https://bugs.webkit.org/show_bug.cgi?id=11089">a
  bug</a> anyway.

  <p>If <var title="">command</var> is "subscript" or "superscript" and <var title="">new
  value</var> is "subscript", let <var title="">new parent</var> be the result of
  calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("sub")</a></code> on the <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.

  <li>If <var title="">command</var> is "subscript" or "superscript" and <var title="">new
  value</var> is "superscript", let <var title="">new parent</var> be the result of
  calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("sup")</a></code> on the <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">node</var>.

  <li>If <var title="">new parent</var> is null, let <var title="">new parent</var> be the result
  of calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("span")</a></code> on the <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of
  <var title="">node</var>.

  <li>
  <p class=comments>This preserves boundary points correctly, as usual.

  <p>Insert <var title="">new parent</var> in <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> before
  <var title="">node</var>.

  <li>If the <a href=#effective-command-value>effective command value</a> of <var title="">command</var> for
  <var title="">new parent</var> is not <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">new value</var>,
  and the <a href=#relevant-css-property>relevant CSS property</a> for <var title="">command</var> is not
  null, set that CSS property of <var title="">new parent</var> to <var title="">new value</var>
  (if the new value would be valid).

  <p class=XXX>Need to be explicit.  I think "if the new value would be valid"
  means "if the new value isn't xxx-large for font-size", need to double-check.

  <li>If <var title="">command</var> is "strikethrough", and <var title="">new value</var> is
  "line-through", and the <a href=#effective-command-value>effective command value</a> of
  "strikethrough" for <var title="">new parent</var> is not "line-through", set the
  "text-decoration" property of <var title="">new parent</var> to "line-through".

  <li>If <var title="">command</var> is "underline", and <var title="">new value</var> is
  "underline", and the <a href=#effective-command-value>effective command value</a> of "underline" for
  <var title="">new parent</var> is not "underline", set the "text-decoration" property
  of <var title="">new parent</var> to "underline".

  <li>Append <var title="">node</var> to <var title="">new parent</var> as its last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>,
  <a href=#preserving-ranges>preserving ranges</a>.

  <li>If <var title="">node</var> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> and the <a href=#effective-command-value>effective command
  value</a> of <var title="">command</var> for <var title="">node</var> is not
  <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">new value</var>:

  <ol>
    <li>Insert <var title="">node</var> into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">new parent</var>
    before <var title="">new parent</var>, <a href=#preserving-ranges>preserving ranges</a>.

    <li>Remove <var title="">new parent</var> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Let <var title="">children</var> be all <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> of <var title="">node</var>,
    omitting any that are <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>s whose <a href=#specified-command-value>specified command
    value</a> for <var title="">command</var> is neither null nor <a href=#equivalent-values title="equivalent values">equivalent</a> to <var title="">new value</var>.

    <li><a href=#force-the-value>Force the value</a> of each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> in <var title="">children</var>,
    with <var title="">command</var> and <var title="">new value</var> as in this invocation of
    the algorithm.
  </ol>
</ol>

<p>To <dfn id=reorder-modifiable-descendants>reorder modifiable descendants</dfn> of a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var>,
given a <a href=#command>command</a> <var title="">command</var> and a value <var title="">new
value</var>:

<ol>
  <li>Let <var title="">candidate</var> equal <var title="">node</var>.

  <li>While <var title="">candidate</var> is a <a href=#modifiable-element>modifiable element</a>, and
  <var title="">candidate</var> has exactly one <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is also a
  <a href=#modifiable-element>modifiable element</a>, and <var title="">candidate</var> is not a
  <a href=#simple-modifiable-element>simple modifiable element</a> or <var title="">candidate</var>'s
  <a href=#specified-command-value>specified command value</a> for <var title="">command</var> is not <a href=#equivalent-values title="equivalent values">equivalent</a> to <var title="">new value</var>, set
  <var title="">candidate</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>.

  <li>If <var title="">candidate</var> is <var title="">node</var>, or is not a <a href=#simple-modifiable-element>simple
  modifiable element</a>, or its <a href=#specified-command-value>specified command value</a> is not
  <a href=#equivalent-values title="equivalent values">equivalent</a> to <var title="">new value</var>, or
  its <a href=#effective-command-value>effective command value</a> is not <a href=#loosely-equivalent-values title="loosely
  equivalent values">loosely equivalent</a> to <var title="">new value</var>, abort
  these steps.

  <li>While <var title="">candidate</var> has <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, insert the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>
  of <var title="">candidate</var> into <var title="">candidate</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> immediately
  before <var title="">candidate</var>, <a href=#preserving-ranges>preserving ranges</a>.

  <li>
  <div class=comments>
  <p>If candidate had no children, any boundary point inside it will get moved to
  its parent here, which is okay.  We don't want to preserve ranges, because
  that would move boundary points that originally were in candidate but were
  moved to its parent by the last step to move to node's parent.

  <p>We move to after node so that boundary points before and after node wind up
  consistently inside candidate when we move preserving ranges.  If we had
    <pre>{&lt;node&gt;foo&lt;candidate&gt;&lt;/candidate&gt;&lt;/node&gt;}</pre>
  <p>it thus becomes
    <pre>{&lt;node&gt;foo&lt;/node&gt;}&lt;candidate&gt;&lt;/candidate&gt;</pre>
  <p>by the range mutation rules, and then when we move preserving ranges, it
  becomes
    <pre>&lt;candidate&gt;{&lt;node&gt;foo&lt;/node&gt;}&lt;/candidate&gt;</pre>
  <p>which is reasonable.

  <p>If we had inserted candidate before node, instead it would go
<pre>{&lt;candidate&gt;&lt;/candidate&gt;&lt;node&gt;foo&lt;/node&gt;}
{&lt;candidate&gt;&lt;node&gt;foo&lt;/node&gt;}&lt;/candidate&gt;</pre>
  <p>because of the interaction of regular range mutation rules with
  preserving-ranges rules.
  </div>

  <p>Insert <var title="">candidate</var> into <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> immediately
  after <var title="">node</var>.

  <li>Append the <var title="">node</var> as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">candidate</var>,
  <a href=#preserving-ranges>preserving ranges</a>.
</ol>


<h3 id="setting-the-selection's-value">Setting the selection's value</h3>

<p>To <dfn id="set-the-selection's-value">set the selection's value</dfn> to <var title="">new value</var>:

<div class=note>
<p>The effect of this algorithm is to ensure that all nodes <a href=#effectively-contained>effectively
contained</a> in the selection have the value requested, producing the
simplest markup possible to achieve that effect.  It's inspired by the approach
WebKit takes.  The only places where the algorithm should fail are when there's
an !important CSS rule that conflicts with the requested style (which we don't
try to override because we assume it's !important for a reason), or when it's
literally impossible to succeed (such as when a text-decoration or link URL is
propagated from a non-editable ancestor).  Any other failures are bugs.

<p>First, if a node has a <a href=#specified-command-value>specified command value</a> for the command,
we unset it (<a href=#clear-the-value title="clear the value">clear its value</a>).  This step
also removes <a href=#simple-modifiable-element title="simple modifiable element">simple modifiable
elements</a> entirely, and replaces elements like <code class=external data-anolis-spec=html title="the b element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-b-element>b</a></code> or <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code> with
<code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-span-element>span</a></code>s if they aren't simple modifiable elements.  This will be sufficient
if the desired value is inherited from an ancestor, or if it's the default
(like font-style: normal) and no conflicting value is inherited from an
ancestor.  Even if clearing values doesn't actually fix the style of the node
we're dealing with, we do it anyway to simplify the generated markup.

<p>If clearing values didn't work, and it looks like an ancestor has a
<a href=#specified-command-value>specified command value</a> that we're inheriting, we push the value
down from that ancestor.  Thus if we're unbolding the letter "r" in

</p><xmp><b>foo <i>bar</i> baz</b>,</xmp>

<p>we get

</p><xmp><b>foo </b><i><b>ba</b>r</i><b> baz</b>.</xmp>

<p>If we didn't push down values, the final step (forcing values) would instead
give us

</p><xmp><b>foo <i>ba<span style="font-weight: normal">r</span></i> baz</b>,</xmp>

<p>which is much longer and uglier.  We take care not to disturb the style or
semantics of anything but the node we're dealing with.

<p>We'll only push down values if some ancestor actually has the value we want,
so we can inherit it.  Otherwise, it will just create useless markup.

<p>Finally, if neither of the above strategies worked, we have to add new
markup to get the desired value (<a href=#force-the-value title="force the value">forcing the
value</a>).  First we try just sticking it into its previous or next
sibling, if that's a <a href=#simple-modifiable-element>simple modifiable element</a> (so it won't add
any styles or semantics we don't want).  Otherwise, we create a new simple
modifiable element and wrap it in that.  It's common that a previous sibling is
the simple modifiable element we want, because often we'll set the value of
several consecutive siblings in succession.  In that case, the element created
for the first can be reused for the later ones.

<p>This last step works a bit differently if the node isn't an <a href=#allowed-child>allowed
child</a> of "span".  In that case, wrapping it in a simple modifiable element
would make the document less conforming than it already was, or would cause
other problems.  Instead, we recursively force the value of its children.  The
recursion will terminate when we hit a node that's an allowed child of "span",
or when there are no further descendants.  (In the latter case, there are no
descendants that are text nodes or such, so we don't really need to style
anything.)

<p>After all this, the node is guaranteed to have the value we want, barring
bugs in the algorithm or the two exceptions noted earlier (!important style
rules, and impossible cases).  We then re-run the algorithm on each child
recursively.  Typically this means just clearing the value of each descendant,
because it should then inherit the value we just set on its ancestor.  In the
unusual case that a descendant's value is wrong even after we clear its value,
such as because of a non-inline style rule (like trying to unbold a heading),
we'll repeat the above steps to ensure that the value really gets set as
desired.
</div>

<ol>
  <li>Let <var title="">command</var> be the current <a href=#command>command</a>.

  <li>
  <p class=comments>IE9 seems to wrap the whole line instead, or something like
  that, although it does nothing for createLink.  We follow all other browsers'
  general behavior: change the state/value, and then make sure that takes
  effect if the user types something before changing the cursor position.

  <p>If there is no <a href=#formattable-node>formattable node</a> <a href=#effectively-contained>effectively
  contained</a> in the <a href=#active-range>active range</a>:

  <ol>
    <li>If <var title="">command</var> has <a href=#inline-command-activated-values>inline command activated values</a>,
    set the <a href=#state-override>state override</a> to true if <var title="">new value</var> is
    among them and false if it's not.

    <li>If <var title="">command</var> is "subscript", unset the <a href=#state-override>state
    override</a> for "superscript".

    <li>If <var title="">command</var> is "superscript", unset the <a href=#state-override>state
    override</a> for "subscript".

    <li>If <var title="">new value</var> is null, unset the <a href=#value-override>value override</a>
    (if any).

    <li>Otherwise, if <var title="">command</var> is "createLink" or it has a
    <a href=#value>value</a> specified, set the <a href=#value-override>value override</a> to
    <var title="">new value</var>.

    <li>Abort these steps.
  </ol>

  <li>
  <p class=comments>The last sentence here just prettifies the resulting range
  a bit.

  <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is an
  <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is neither zero
  nor its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=dom title=dom-Text-splitText><a href=http://dom.spec.whatwg.org/#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, with argument equal to the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a>.  Then set the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> to the result, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> to zero.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a> is an
  <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-offset title=concept-range-end-offset>end offset</a> is neither zero
  nor its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=dom title=dom-Text-splitText><a href=http://dom.spec.whatwg.org/#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>, with argument equal to the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-offset title=concept-range-end-offset>end offset</a>.

  <li>Let <var title="">element list</var> be all <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>s
  <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>.

  <li>For each <var title="">element</var> in <var title="">element list</var>, <a href=#clear-the-value>clear the
  value</a> of <var title="">element</var>.

  <li>
  <div class=comments>
  <p>We skip non-editable nodes.

  <dl>
    <dt>IE9
    <dd>Allows everything to be modified by execCommand(), regardless of
    whether it's editable.

    <dt>Firefox 4.0
    <dd>Ignores execCommand() if the start and end of the selection are not
    both editable.  If the start and end are editable but something in the
    middle is not, seems to relocate the non-editable part in the middle or
    something like that.

    <dt>Chrome 12 dev
    <dd>Ignores execCommand() if the start and end of the selection are not
    both editable.  If the start and end are editable but something in the
    middle is not, applies the given command but skips the non-editable parts.
    But the state doesn't ignore the non-editable parts, so if you bold such a
    selection you can't unbold it, for instance, since the middle part will
    remain bold (so it will keep on trying to bold it instead of switching to
    unbold).

    <dt>Opera 11.00
    <dd>Ignores execCommand() if the start and end of the selection are not
    both editable.  If the start and end are editable but something in the
    middle is not, applies the command to everything, even the non-editable
    part.
  </dl>

  <p>I chose to go with the non-IE behavior, per <a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-April/031147.html>discussion</a>.
  Ignoring non-editable things is convenient for the common use-case of an
  editor, where you don't want the user to bold random parts of the UI when
  they hit the bold button.  For cases where it's not desired, you can always
  turn designMode on briefly before using execCommand(), so the non-IE behavior
  is a lot easier to work around than the IE behavior.

  <p>I don't see the value in ever just ignoring execCommand().  If the start
  and end are not editable, I'm going to say you should still style any
  editable nodes in between.  I'm also going to ignore non-editable nodes for
  the purposes of determining state, so (for instance) if all the editable
  nodes are bolded, it will unbold instead of bolding.
  </div>

  <p>Let <var title="">node list</var> be all <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>
  <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>.

  <li>
  <p class=comments>TODO: This is inefficient.  It would be most efficient to
  only push down values on the highest-level effectively contained nodes, and
  to batch operations so we handle runs of adjacent siblings at once.  Should
  we bother fixing this?

  <p>For each <var title="">node</var> in <var title="">node list</var>:

  <ol>
    <li><a href=#push-down-values>Push down values</a> on <var title="">node</var>.

    <li>
    <p class=comments>If the node isn't an allowed child of "span", forcing its
    value will just force its children's value, which is redundant.  So don't.

    <p>If <var title="">node</var> is an <a href=#allowed-child>allowed child</a> of "span",
    <a href=#force-the-value>force the value</a> of <var title="">node</var>.
  </ol>
</ol>


<h3 id=the-backcolor-command><dfn>The <code title="">backColor</code> command</dfn></h3>

<p class=note>For historical reasons, backColor and hiliteColor behave
identically.

<div class=comments>
<p>We have three behaviors to choose from for this one:

<ol>
  <li>Chrome 11 dev and IE 9 RC treat it the same as hiliteColor (although IE 9
  RC doesn't support hiliteColor itself).

  <li>Firefox 4 in non-CSS mode sets the bgcolor of the nearest td or body, or
  something like that.  In testing, it seems to jump out of contenteditable
  elements to style non-editable ancestors, which is alarming.

  <li>Firefox 4 in CSS mode and Opera 11 set the background of the nearest
  block container, although it doesn't seem to be very dependable (probably I
  just don't get what exactly it's doing).
</ol>

<p>(1) is obviously redundant, but has plurality support, so we could spec it
that way if the other ways were useless.

<p>(3) is incoherent from a user perspective.  For instance, if you try it on
paragraphs the background will have big gaps where the margins are.  If you try
it on an inline element that's a child of the editing host, it will do nothing
or apply the background to everything or such, even though such an inline
element is visually indistinguishable from one sitting inside a div.  This
would only make sense if we take considerable effort to ensure that block
elements all have no margins, or if we wrap things in a div if they have
margins, or something like that.

<p>That leaves (2).  That might be useful if it actually set the document's
background color, but it seems like it sets table cell backgrounds sometimes
instead, which is really confusing.

<p>The path of least resistance is to standardize this as meaning the same
thing as hiliteColor, and make up new commands if we want to do things like set
the document background color.  See hiliteColor for comments.
</div>

<p><a href=#action>Action</a>:

<ol>
  <li>If <var title="">value</var> is not a valid CSS color, prepend "#" to it.

  <li>If <var title="">value</var> is still not a valid CSS color, or if it is
  currentColor, return false.

  <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.

  <li>Return true.
</ol>

<p><a href=#standard-inline-value-command>Standard inline value command</a>

<p><a href=#relevant-css-property>Relevant CSS property</a>: "background-color"

<p><a href=#equivalent-values>Equivalent values</a>: Either both strings are valid CSS colors and
have the same red, green, blue, and alpha components, or neither string is a
valid CSS color.


<h3 id=the-bold-command><dfn>The <code title="">bold</code> command</dfn></h3>

<p class=comments>If the selection is collapsed (but not if it contains nothing
but is not collapsed), IE9 wraps the whole line in a &lt;strong&gt;.  This seems
bizarre and no one else does it, so I don't do it.  It's a similar story for
similar commands (fontName, italic, etc.).  Except not for strikethrough, where
it just does nothing if the selection is empty.  Why strikethrough?  I don't
know.

<p><a href=#action>Action</a>: If <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("bold")</a></code> returns true,
<a href="#set-the-selection's-value">set the selection's value</a> to "normal".  Otherwise <a href="#set-the-selection's-value">set the
selection's value</a> to "bold".  Either way, return true.

<div class=comments>
<p>The cutoff of 600 matches Chrome 14 dev.  The cutoff used by IE9 and Firefox
6.0a2 seems to be 500, and the distinction isn't relevant for Opera 11.11 (it
doesn't use CSS here at all AFAICT).  On my test systems with default fonts,
Chrome 14 dev displays 700 and up as bold, while the other three display 600
and up as bold.

<p>Thus in Chrome on my system, the bold command will behave a bit oddly the first
time you hit it if there's anything in the range with font-weight: 600, but it
will look right in other browsers.  On the other hand, if I followed
IE/Firefox, it would look wrong on all my browsers for font-weight: 500.

<p>700 actually makes more sense: then you'd view 100-300 as light, 400-600 as
medium, 700-900 as bold.  But that's not how it seems to work in browsers, so
I'll go with 600 as the cutoff.
</div>

<p><a href=#inline-command-activated-values>Inline command activated values</a>: "bold", "600", "700", "800",
or "900"

<p><a href=#relevant-css-property>Relevant CSS property</a>: "font-weight"

<p><a href=#equivalent-values>Equivalent values</a>: Either the two strings are equal, or one is
"bold" and the other is "700", or one is "normal" and the other is "400".


<h3 id=the-createlink-command><dfn>The <code title="">createLink</code> command</dfn></h3>

<div class=comments>
<p>If the selection doesn't contain anything (meaning, e.g., deleteContents()
doesn't change anything), then Chrome 12 dev inserts a link at the selection
start, with the text equal to the link URL.  Other browsers don't do it, so I
don't either.

<p>IE10PP2, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all do not support
indeterminate, state, or value for createLink or unlink.  I previously defined
indeterminate and value anyway because they make sense, but then <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14067">undefined them</a>.
The nontrivial thing is what value to return if there's no link, since any
string can occur as a link href, in principle.

<p>What are the use-cases for indeterm, state, or value for createLink/unlink?
</div>

<p><a href=#action>Action</a>:

<ol>
  <li>
  <p class=comments> Firefox 4b11 and Chrome 11 dev both silently do nothing in
  this case.  IE 9 RC and Opera 11 both treat the request literally.  Gecko and
  WebKit probably have it right here: users who enter no URL are very unlikely
  to want to link to a relative URL resolving to the current document.  If they
  really want to, they can always specify "#" for the value, or the author can
  rewrite it, so it's not like this makes the API less useful.

  <p>If <var title="">value</var> is the empty string, return false.

  <li>
  <div class=comments>
  <p>There are three approaches here.  For instance, if you ask browsers to
  create a link to "http://example.org" on the "b" here:

    <pre>&lt;a href=http://example.com&gt;&lt;b&gt;Abc&lt;/b&gt;&lt;/a&gt;</pre>

  <p>Chrome 10 dev produces:

    <pre>&lt;b&gt;&lt;a href=http://example.com&gt;A&lt;/a&gt;&lt;a href=http://example.org&gt;b&lt;/a&gt;&lt;a href=http://example.com&gt;c&lt;/a&gt;&lt;/b&gt;</pre>

  <p>Firefox 4b11 produces (roughly):

    <pre>&lt;a href=http://example.com&gt;&lt;b&gt;A&lt;a href=http://example.org&gt;b&lt;/a&gt;c&lt;/b&gt;&lt;/a&gt;</pre>

  <p>(This doesn't round-trip through text/html serialization.)  IE 9 RC and Opera
  11 produce simply:

    <pre>&lt;a href=http://example.org&gt;&lt;b&gt;Abc&lt;/b&gt;&lt;/a&gt;</pre>

  <p>The last behavior probably best matches user expectations.  If you happen to
  miss out a character when selecting the link you want to change, do you
  really intend to only change the link of part of it?
  </div>

  <p>For each <a href=#editable>editable</a> <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> element that has an <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code>
  attribute and is an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of some <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <a href=#effectively-contained>effectively
  contained</a> in the <a href=#active-range>active range</a>, set that <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> element's
  <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code> attribute to <var title="">value</var>.

  <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.

  <li>Return true.
</ol>


<h3 id=the-fontname-command><dfn>The <code title="">fontName</code> command</dfn></h3>

<div class=comments>
<p>UAs differ a bit in the details here:

<dl>
  <dt>IE 9 RC
  <dd>Empty string sets &lt;font face=""&gt;

  <dt>Firefox 4b11
  <dd>Empty string does nothing

  <dt>Chrome 11 dev
  <dd>Empty string does nothing, '"monospace"' same as 'monospace' (i.e.,
  cannot escape font-family keywords because quotes are stripped, clearly
  wrong)

  <dt>Opera 11
  <dd>Empty string sets &lt;font face=""&gt;
</dl>

<p>Setting an empty font-family has the effect of inheriting the font from the
parent (although I don't see where the February 24, 2011 CSS 3 Fonts draft says
that).  Thus it makes sense that if we special-case this, it should be to unset
the font somehow.

<p>Special-casing the empty string to do nothing doesn't make sense to me.  With
createLink we'd expect the user to enter the URL themselves, so it makes sense
to special-case clicking OK without entering anything.  But here it's very
likely that the font list will be fixed by the author (how many users will
understand CSS font-family syntax?), so I don't think such usability concerns
apply.
</div>

<p><a href=#action>Action</a>: <a href="#set-the-selection's-value">Set the selection's value</a> to
<var title="">value</var>, then return true.

<div class=comments>
<p>The value is complicated.

<dl>
  <dt>IE 9 RC
  <dd>Always the empty string.  Not very useful.

  <dt>Firefox 4b11
  <dd>Confusing.  Sometimes it returns generic family names, like "sans-serif".
  Sometimes it gives specific font names, like "tt" when the font is specified
  as "monospace".  Sometimes it gives the literal font-family string.  Not sure
  what it's doing here.

  <dt>Chrome 11 dev
  <dd>Gives the literal value of font-family, except if it's inherited from
  default values (no explicit style declarations anywhere), when it seems to
  return the exact font name.

  <dt>Opera 11
  <dd>Returns the literal value of font-family, except if it's inherited
  from default values, when it returns the empty string.
</dl>

<p>I'm just going to punt on this and say it should be the resolved value of
font-family.  I'll leave CSSOM to decide what that means if there are no
applicable style rules.
</div>

<p><a href=#standard-inline-value-command>Standard inline value command</a>

<p><a href=#relevant-css-property>Relevant CSS property</a>: "font-family"


<h3 id=the-fontsize-command><dfn>The <code title="">fontSize</code> command</dfn></h3>

<div class=comments>
<dl>
  <dt>IE 9
  <dd>Parses the value as a number (allowing floating-point), rounds to the
  nearest integer, then clamps to the range 1 to 7.  If the value is not a
  valid number, including if it has trailing characters (like "2em"), does
  nothing.  Normalizes relative sizes, so "+0" is the same as "+3", etc.
  Treats empty string the same as "1".

  <dt>Firefox 4.0
  <dd>Passes the value through literally to &lt;font size=&gt;, so "2em" gets you
  &lt;font size="2em"&gt;.  Always uses &lt;font&gt;, even with styleWithCss true.
  Ignores the command if the value is the empty string.

  <dt>Chrome 12 dev
  <dd>Parses the value as a legacy font size, so "2em" becomes "2", then
  outputs a &lt;font&gt; with the resulting number.  If there is no resulting
  number, like for a value of "xx-small", does nothing.  In styleWithCss mode,
  outputs a span with corresponding CSS keywords: 1 = x-small, 2 = small, . .
  ., 6 = xx-large, 7 = -webkit-xxx-large.  Normalizes relative sizes, so "+0"
  is the same as "3", etc.  Ignores the command if the value is the empty
  string.

  <dt>Opera 11
  <dd>Parses the value as an integer (ignoring floating-point as trailing
  characters), then outputs that.  This means that "+0" becomes &lt;font
  size=0&gt; instead of &lt;font size=+0&gt; or &lt;font size=3&gt;.  Non-numeric values
  get interpreted as 0.  Does not clamp, and is willing to output negative
  numbers.  Treats empty string as "0".
</dl>

<p>What all of these have in common is that they force the author to deal with
legacy font values and don't let them use CSS.  This is undesirable, but to
avoid it we'd really have to create a new command.  If nothing else, the value
returned by <code title="">queryCommandValue()</code> has to be numeric, so authors can't
really use the command sanely no matter what we do.  See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14251">bug 14251</a>.

<p>Note that 1 is the same size as x-small in browsers, not xx-small, contrary
to the CSS Fonts spec.
</div>

<p><a href=#action>Action</a>:

<ol>
  <li><a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#strip-leading-and-trailing-whitespace>Strip leading and trailing whitespace</a>
  from <var title="">value</var>.

  <li>If <var title="">value</var> is not a <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-floating-point-number>valid floating
  point number</a>, and would not be a <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-floating-point-number>valid
  floating point number</a> if a single leading "+" character were stripped,
  return false.

  <li>If the first character of <var title="">value</var> is "+", delete the character
  and let <var title="">mode</var> be "relative-plus".

  <li>Otherwise, if the first character of <var title="">value</var> is "-", delete the
  character and let <var title="">mode</var> be "relative-minus".

  <li>Otherwise, let <var title="">mode</var> be "absolute".

  <li>Apply the <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#rules-for-parsing-non-negative-integers>rules for parsing non-negative
  integers</a> to <var title="">value</var>, and let <var title="">number</var> be the result.

  <li>If <var title="">mode</var> is "relative-plus", add three to <var title="">number</var>.

  <li>If <var title="">mode</var> is "relative-minus", negate <var title="">number</var>, then
  add three to it.

  <li>If <var title="">number</var> is less than one, let <var title="">number</var> equal 1.

  <li>If <var title="">number</var> is greater than seven, let <var title="">number</var> equal
  7.

  <li>Set <var title="">value</var> to the string here corresponding to
  <var title="">number</var>:

  <p class=comments>The entry for 7 here is an issue: there's no CSS value that
  corresponds to it.  Even if we got one added to the drafts, it wouldn't be
  backward-compatible to use it.  WebKit is the only engine that supports CSS
  output for fontSize, and it uses -webkit-xxx-large in this case, which is
  unworkable.  Instead, we just always output a font tag for size 7.  If
  authors want conforming markup, they'll need to give CSS sizes above size 7,
  not legacy sizes.

  <ul>
    <li>1: x-small
    <li>2: small
    <li>3: medium
    <li>4: large
    <li>5: x-large
    <li>6: xx-large
    <li>7: xxx-large
  </ul>

  <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.

  <li>Return true.
</ol>

<p class=comments>This follows Firefox 6.0a2.  Chrome 14 dev always returns
false.  Note that indeterminacy here keys off the effective command value,
while the value is based only on an approximation (a number from one to seven).
Thus it's possible for every subrange of the selection to have the same value,
but for the selection to still be indeterminate.  Setting the fontSize to the
value will make it determinate without changing anything's value.

<p><a href=#indeterminate>Indeterminate</a>: True if among <a href=#formattable-node title="formattable
node">formattable nodes</a> that are <a href=#effectively-contained>effectively contained</a> in
the <a href=#active-range>active range</a>, there are two that have distinct <a href=#effective-command-value title="effective command value">effective command values</a>.  Otherwise
false.

<div class=comments>
<dl>
  <dt>IE9
  <dd>Seems to return a number based on the computed font-size, but only if
  it's exactly right, otherwise it returns null.  Something like that.

  <dt>Firefox 6.0a2
  <dd>Seemingly goes up to the nearest ancestor that's a &lt;font size&gt; and
  returns the literal value of that attribute, or "" if there's no such
  ancestor.

  <dt>Chrome 14 dev
  <dd>Gets the computed font-size in pixels, and rounds to the nearest &lt;font
  size&gt; equivalent, rounding up in the event of a tie.  Except that if it's
  small enough, it returns "0", which doesn't make sense because that behaves
  the same as "1".

  <dt>Opera 11.11
  <dd>Like Firefox, except it returns "3" if there's no &lt;font size&gt;
  ancestor, and it converts relative values to absolute ("+1" -&gt; "4").
</dl>

<p>Chrome's behavior seems the most useful.  As usual, IE returns a variable
type and all other browsers return strings, and we follow other browsers.

<p>If the selection isn't someplace editable, Chrome works like usual; some
other browsers behave differently.  I see no reason to behave differently.
</div>

<p><a href=#value>Value</a>:

<ol>
  <li>If the <a href=#active-range>active range</a> is null, return the empty string.

  <li>
  <p class=comments>See comment for standard inline value commands on how I
  decided on this choice of node.

  <p>Let <var title="">pixel size</var> be the <a href=#effective-command-value>effective command value</a> of
  the first <a href=#formattable-node>formattable node</a> that is <a href=#effectively-contained>effectively
  contained</a> in the <a href=#active-range>active range</a>, or if there is no such
  node, the <a href=#effective-command-value>effective command value</a> of the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, in either case interpreted as a number of
  pixels.

  <li>Return the <a href=#legacy-font-size-for>legacy font size for</a> <var title="">pixel size</var>.
</ol>

<p><a href=#relevant-css-property>Relevant CSS property</a>: "font-size"

<p>The <dfn id=legacy-font-size-for>legacy font size for</dfn> an integer <var title="">pixel size</var> is
returned by the following algorithm:

<ol>
  <li>Let <var title="">returned size</var> be 1.

  <li>While <var title="">returned size</var> is less than 7:

  <ol>
    <li>Let <var title="">lower bound</var> be the <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> of "font-size" in pixels
    of a <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code> element whose <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-size>size</a></code> attribute is set to <var title="">returned
    size</var>.

    <li>Let <var title="">upper bound</var> be the <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> of "font-size" in pixels
    of a <code class=external data-anolis-spec=html title=font><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#font>font</a></code> element whose <code class=external data-anolis-spec=html title=dom-font-size><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dom-font-size>size</a></code> attribute is set to one plus
    <var title="">returned size</var>.

    <li>Let <var title="">average</var> be the average of <var title="">upper bound</var> and
    <var title="">lower bound</var>.

    <li>If <var title="">pixel size</var> is less than <var title="">average</var>, return the
    one-<a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> string consisting of the digit <var title="">returned size</var>.

    <li>Add one to <var title="">returned size</var>.
  </ol>

  <li>Return "7".
</ol>

<h3 id=the-forecolor-command><dfn>The <code title="">foreColor</code> command</dfn></h3>

<div class=comments>
<p>Color interpretations:

<!-- I wanted the table to stretch out to the left.  CSS doesn't support this
directly, but where there's a will, there's a way! -->
<div style=height:1px;background:white;z-index:2;position:absolute;left:0;right:0></div>
<pre style="white-space:pre; overflow:auto; float:right; background:white;
padding:0.5em; border: 1px solid gray; border-right: none; margin-top: 0;
margin-bottom: 0">                        IE10PP2       Firefox 7.0a2            Chrome 14 dev            Opera 11.50
blue                    blue          blue                     #0000ff                  #0000ff
f                       #f            -                        -                        #f00000
#f                      #f            -                        -                        #f00000
00f                     #00f          -                        #0000ff                  #00000f
#00f                    #00f          rgb(0, 0, 255)           #0000ff                  #00000f
0000ff                  #0000ff       -                        #0000ff                  #0000ff
#0000ff                 #0000ff       rgb(0, 0, 255)           #0000ff                  #0000ff
000000fff               #0000ff       -                        -                        -
#000000fff              #0000ff       -                        -                        -
rgb(0, 0, 255)          rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
rgb(0%, 0%, 100%)       rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
rgb( 0 ,0 ,255)         rgb(0,0,255)  rgb(0, 0, 255)           #0000ff                  #00b000
rgba(0, 0, 255, 0.0)    #ba0000       rgba(0, 0, 255, 0)       rgba(0, 0, 255, 0)       #00ba00
rgb(15, -10, 375)       rgb(15,0,255) rgb(15, 0, 255)          #0f00ff                  #00b015
rgba(0, 0, 0, 1)        #ba0010       rgb(0, 0, 0)             -                        #00ba00
rgba(255, 255, 255, 1)  #000055       rgb(255, 255, 255)       #ffffff                  #00ba02
rgba(0, 0, 255, 0.5)    #ba0000       rgba(0, 0, 255, 0.5)     rgba(0, 0, 255, 0.5)     #00ba00
hsl(240, 100%, 50%)     #000150       rgb(0, 0, 255)           #0000ff                  #000024
cornsilk                cornsilk      cornsilk                 #fff8dc                  #fff8dc
potato quiche           #0000c0       -                        -                        #000a00
transparent             transparent   -                        rgba(0, 0, 0, 0)         #00a000
currentColor            #c0e000       currentcolor             rgba(0, 0, 0, 0)         #c000e0</pre>
<div style=clear:right></div>
<div style=height:1px;background:white;z-index:2;position:absolute;left:0;right:0;margin-top:-1px></div>

<p>The interpretations given for Firefox are only in styleWithCSS mode.  In
non-styleWithCSS mode, it just outputs the string literally as the &lt;font
color&gt; attribute value, which can lead to different results.  The given output
for Chrome is for &lt;font&gt;; the output in styleWithCSS mode is the same, but
rgb() is used instead of hex notation, and "transparent" and "currentcolor" are
passed through under those names.  IE and Opera only support &lt;font&gt; to begin
with.

<p>Conclusions:

<ul>
  <li>Everyone accepts simple color keywords and #xxxxxx notation.

  <li>Opera mangles #xxx, but everyone else handles it fine.

  <li>The leading # is optional in all browsers but Gecko.

  <li>rgb() is accepted by everyone but Opera.

  <li>rgba() and hsl() are accepted by Gecko and WebKit, but rejected by IE and
  Opera.

  <li>IE and Opera mangle unrecognized stuff, Gecko and WebKit ignore.

  <li>Browsers will happily output stuff like "transparent" and "rgba()" into
  &lt;font color&gt; even though it won't be uniformly accepted there.

  <li>Opera and WebKit normalize the output color very aggressively, Gecko
  leaves keywords intact but otherwise normalizes for CSS output (but doesn't
  normalize at all for &lt;font&gt;), and IE normalizes inconsistently.
</ul>

<p>What I'm going to say is that it either has to be a valid CSS color, or
prefixing it with # must result in a valid CSS color.  For <code title="">&lt;font&gt;</code>,
I'll say that the output color should be normalized to #xxxxxx form.  If the
color is not a simple color (fully opaque with all channels between 0 and 255),
I'll force <code title="">style=""</code> even if styleWithCSS mode is off.  Some of this
disagrees with all browsers, but it's unlikely to hurt and it makes sense.
</div>

<p><a href=#action>Action</a>:

<ol>
  <li>
  <p class=comments>TODO: Define "valid CSS color" (here and in other color
  places).

  <p>If <var title="">value</var> is not a valid CSS color, prepend "#" to it.

  <li>
  <p class=comments>currentColor is bad for the same reason as relative font
  sizes.  It will confuse the algorithm, and doesn't seem very useful anyway.

  <p>If <var title="">value</var> is still not a valid CSS color, or if it is
  currentColor, return false.

  <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.

  <li>Return true.
</ol>

<div class=comments>
<p>Opera 11 seems to return true for the state if there's some
color style applied, false otherwise, which seems fairly useless; authors want
to use value here, not state.  So I'll match other browsers and not define any
state.

<p>For value, the spec essentially matches Firefox 6.0a2 and Chrome 14 dev, as
far as how to decide what color the node has.  IE9 seems to always return the
number 0 for some bizarre reason.  There are some cases where Firefox returns
the empty string for some reason, and it seems to select the active node a
little differently.  Opera uses #xxxxxx format for getComputedStyle() but rgb()
here, and also drops the transparent part of the color if there is any.
</div>

<p><a href=#standard-inline-value-command>Standard inline value command</a>

<p><a href=#relevant-css-property>Relevant CSS property</a>: "color"

<p><a href=#equivalent-values>Equivalent values</a>: Either both strings are valid CSS colors and
have the same red, green, blue, and alpha components, or neither string is a
valid CSS color.


<h3 id=the-hilitecolor-command><dfn>The <code title="">hiliteColor</code> command</dfn></h3>

<p class=note>For historical reasons, backColor and hiliteColor behave
identically.

<div class=comments>
<p>IE 9 RC doesn't support this.  It uses backColor instead, but Gecko and
Opera treat that differently, while all non-IE browsers treat hiliteColor the
same, so I'm standardizing hiliteColor as the way to highlight text.

<p>This is slightly tricky, because background-color does different things on
block and inline elements.  Given the name ("hiliteColor"), we really only want
to apply it to inline elements.  This is how everyone but Gecko behaves, but
Gecko sometimes applies it to blocks too.  WebKit doesn't set it on non-inline
elements, but does clear it and push it down from them.

<p>The spec doesn't do any of these: background-color on non-inline elements is
not touched by hiliteColor, neither created nor removed.  If users want to
remove the style, they need to use removeFormat.  Adding it usually makes no
sense; see the comment for backColor.

<p>For color parsing, see the comment for foreColor.

<p>See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13829">bug
13829</a>.
</div>

<p><a href=#action>Action</a>:

<ol>
  <li>If <var title="">value</var> is not a valid CSS color, prepend "#" to it.

  <li>
  <p class=comments>currentColor is bad for the same reason as relative font
  sizes.  It will confuse the algorithm, and doesn't seem very useful anyway.
  For hiliteColor you could conceive of it being useful, but it will still
  confuse the algorithm, so ban it for now anyway.

  <p>If <var title="">value</var> is still not a valid CSS color, or if it is
  currentColor, return false.

  <li><a href="#set-the-selection's-value">Set the selection's value</a> to <var title="">value</var>.

  <li>Return true.
</ol>

<p class=comments>For indeterminacy, this follows no one.  Firefox 6.0a2 and
Chrome 14 dev both always return false.  However, the spec makes sense, since
it's consistent with other commands.

<p><a href=#standard-inline-value-command>Standard inline value command</a>

<p><a href=#relevant-css-property>Relevant CSS property</a>: "background-color"

<p><a href=#equivalent-values>Equivalent values</a>: Either both strings are valid CSS colors and
have the same red, green, blue, and alpha components, or neither string is a
valid CSS color.


<h3 id=the-italic-command><dfn>The <code title="">italic</code> command</dfn></h3>

<p><a href=#action>Action</a>: If <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("italic")</a></code> returns true,
<a href="#set-the-selection's-value">set the selection's value</a> to "normal".  Otherwise <a href="#set-the-selection's-value">set the
selection's value</a> to "italic".  Either way, return true.

<p><a href=#inline-command-activated-values>Inline command activated values</a>: "italic" or "oblique"

<p><a href=#relevant-css-property>Relevant CSS property</a>: "font-style"


<h3 id=the-removeformat-command><dfn>The <code title="">removeFormat</code> command</dfn></h3>

<div class=comments>
<p>See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13632">bug</a>, and
also <a href="https://bugs.webkit.org/show_bug.cgi?id=43017">research by Ryosuke
for WebKit</a>.

<p>Tested in IE 9, Firefox 4.0, Chrome 12 dev, Opera 11.00.

<ul>
<li>Tags stripped by everyone: b big cite code dfn em font i ins kbd s samp
small strike strong sub sup tt u var

<li>Tags left alone by everyone: br hr img

<li>Unrecognized elements: stripped by Firefox and Opera, left alone by IE and
Chrome.

<li>blink: stripped only by IE
<li>abbr: stripped only by Firefox
<li>a, wbr: stripped only by Opera

<li>nobr: left alone only by Firefox
<li>acronym, bdo, q: left alone only by Opera

<li>bdi, del, mark, span, svg: treated the same as unknown elements
</ul>

<p>All elements whose default rendering is display: block are left untouched by
all browsers (although IE seems to throw an exception on &lt;marquee&gt; for some
reason).

<p>It's not clear to me why we should leave &lt;a&gt; alone, but everyone but Opera
does.  In OpenOffice.org 3.2.1, doing "Default Formatting (Ctrl+M)" doesn't
remove links.  In Microsoft Word 2007, doing "Clear Formatting" also doesn't
remove links.  Verdict: don't remove links.  Apparently they don't logically
qualify as "formatting".

<p>Conclusion: IE/WebKit is a solid majority by market share and they're
closely interoperable, since WebKit copied IE here.  Also, it makes more sense
to assume that unrecognized elements don't represent any kind of inline
formatting, i.e., have a blacklist of elements to remove instead of a whitelist
to keep.  Thus I remove more or less the same things as IE/WebKit.

<p>I remove blink because IE does it and it makes sense, although Chrome
doesn't; I remove abbr although only Firefox does, for consistency with
acronym; and I remove bdi and mark because they're evidently left alone only
because they're unrecognized.  Finally, I remove span because otherwise,
something like <code title="">&lt;span style="font-variant: small-caps"&gt;</code>
will be left intact, which isn't expected and matches no browser except IE.
(Chrome doesn't remove spans in general, but it does remove spans with style
attributes, or something like that.)

<p>Browsers will split up all these inline elements if the selection is contained
within them.  Opera does strip unrecognized elements with display: block if
they're within the selection, but doesn't split them up if they contain the
selection.

<p>Chrome 14 dev removes style attributes from every element in the range, but
IE10PP2, Firefox 7.0a2, and Opera 11.50 do not, so I go with them.  As noted
above, this means I need to remove spans.  I could conceivably change to remove
only spans with style attributes, but it doesn't seem worth it: I'll just match
Gecko.

<p>TODO: This has to be kept in sync when new HTML elements are added.  I need
to figure out some way of coordinating this.
</div>

<p>A <dfn id=removeformat-candidate>removeFormat candidate</dfn> is an <a href=#editable>editable</a> <a href=#html-element>HTML
element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> "abbr", "acronym", "b", "bdi", "bdo", "big",
"blink", "cite", "code", "dfn", "em", "font", "i", "ins", "kbd", "mark",
"nobr", "q", "s", "samp", "small", "span", "strike", "strong", "sub", "sup",
"tt", "u", or "var".

<p><a href=#action>Action</a>:

<ol>
  <li>Let <var title="">elements to remove</var> be a list of every <a href=#removeformat-candidate>removeFormat
  candidate</a> <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active
  range</a>.

  <li>For each <var title="">element</var> in <var title="">elements to remove</var>:

  <ol>
    <li>While <var title="">element</var> has <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, insert the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>
    of <var title="">element</var> into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">element</var> immediately
    before <var title="">element</var>, <a href=#preserving-ranges>preserving ranges</a>.

    <li>Remove <var title="">element</var> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
  </ol>

  <li>
  <p class=comments>The last sentence just prettifies the resulting range a
  bit.

  <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is an
  <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is neither zero
  nor its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=dom title=dom-Text-splitText><a href=http://dom.spec.whatwg.org/#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, with argument equal to the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a>.  Then set the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> to the result, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> to zero.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a> is an
  <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-offset title=concept-range-end-offset>end offset</a> is neither zero
  nor its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, call <code class=external data-anolis-spec=dom title=dom-Text-splitText><a href=http://dom.spec.whatwg.org/#dom-text-splittext>splitText()</a></code> on the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>, with argument equal to the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-offset title=concept-range-end-offset>end offset</a>.

  <li>Let <var title="">node list</var> consist of all <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>
  <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>.

  <li>
  <p class=comments>TODO: Splitting the parent is really a block algorithm.
  It's not clear whether it's desirable to use for inline nodes.  Perhaps it's
  okay, but it makes me a little uneasy.

  <p>For each <var title="">node</var> in <var title="">node list</var>, while <var title="">node</var>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is a <a href=#removeformat-candidate>removeFormat candidate</a> <a href=#in-the-same-editing-host>in the same editing
  host</a> as <var title="">node</var>, <a href=#split-the-parent>split the parent</a> of the
  one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of <var title="">node</var>.

  <li>
  <p class=comments>This step is for cases like &lt;p
  style=font-weight:bold&gt;foo[bar]baz&lt;/p&gt;, where splitting/removing tags
  won't help.  We don't need to run superscript, since subscript does the same
  thing here.  We run subscript first so &lt;sub&gt;/&lt;sup&gt; won't upset
  fontSize.

  <p>For each of the entries in the following list, in the given order,
  <a href="#set-the-selection's-value">set the selection's value</a> to null, with <var title="">command</var> as
  given.

  <ol>
    <li>subscript
    <li>bold
    <li>fontName
    <li>fontSize
    <li>foreColor
    <li>hiliteColor
    <li>italic
    <li>strikethrough
    <li>underline
  </ol>

  <li>Return true.
</ol>


<h3 id=the-strikethrough-command><dfn>The <code title="">strikethrough</code> command</dfn></h3>

<p class=comments>TODO: See underline TODO.

<p><a href=#action>Action</a>: If <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("strikethrough")</a></code> returns
true, <a href="#set-the-selection's-value">set the selection's value</a> to null.  Otherwise <a href="#set-the-selection's-value">set the
selection's value</a> to "line-through".  Either way, return true.

<p><a href=#inline-command-activated-values>Inline command activated values</a>: "line-through"


<h3 id=the-subscript-command><dfn>The <code title="">subscript</code> command</dfn></h3>

<p><a href=#action>Action</a>:

<ol>
  <li>Call <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("subscript")</a></code>, and let
  <var title="">state</var> be the result.

  <li><a href="#set-the-selection's-value">Set the selection's value</a> to null.

  <li>If <var title="">state</var> is false, <a href="#set-the-selection's-value">set the selection's value</a> to
  "subscript".

  <li>Return true.
</ol>

<p><a href=#indeterminate>Indeterminate</a>: True if either among <a href=#formattable-node title="formattable
node">formattable nodes</a> that are <a href=#effectively-contained>effectively contained</a> in
the <a href=#active-range>active range</a>, there is at least one with <a href=#effective-command-value>effective
command value</a> "subscript" and at least one with some other
<a href=#effective-command-value>effective command value</a>; or if there is some <a href=#formattable-node>formattable
node</a> <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>
with <a href=#effective-command-value>effective command value</a> "mixed".  Otherwise false.

<p class=comments> For &lt;sup&gt;&lt;sub&gt;foo&lt;/sub&gt;&lt;/sup&gt;, Firefox 6.0a2 and
Opera 11.11 say the state is true for both superscript and subscript, and
indeterminate is false; Chrome 14 dev says it's true for subscript but not
superscript, and indeterminate is false.  We follow neither of these behaviors:
we return false for both states, and say indeterminate is true.  The reason is
because we want to return true for a state if we'll do nothing, false if we'll
do something; and if we have nesting like this, we'll always do something,
namely get rid of all those ancestors and replace them with a single tag.  This
matches what happens in other indeterminate situations, so it's fair to
consider it indeterminate.

<p><a href=#inline-command-activated-values>Inline command activated values</a>: "subscript"


<h3 id=the-superscript-command><dfn>The <code title="">superscript</code> command</dfn></h3>

<p><a href=#action>Action</a>:

<ol>
  <li>Call <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("superscript")</a></code>, and let
  <var title="">state</var> be the result.

  <li><a href="#set-the-selection's-value">Set the selection's value</a> to null.

  <li>If <var title="">state</var> is false, <a href="#set-the-selection's-value">set the selection's value</a> to
  "superscript".

  <li>Return true.
</ol>

<p><a href=#indeterminate>Indeterminate</a>: True if either among <a href=#formattable-node title="formattable
node">formattable nodes</a> that are <a href=#effectively-contained>effectively contained</a> in
the <a href=#active-range>active range</a>, there is at least one with <a href=#effective-command-value>effective
command value</a> "superscript" and at least one with some other
<a href=#effective-command-value>effective command value</a>; or if there is some <a href=#formattable-node>formattable
node</a> <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>
with <a href=#effective-command-value>effective command value</a> "mixed".  Otherwise false.

<p><a href=#inline-command-activated-values>Inline command activated values</a>: "superscript"


<h3 id=the-underline-command><dfn>The <code title="">underline</code> command</dfn></h3>

<div class=comments>
<p>TODO: There are a lot of problems with underline color and thickness,
because text-decoration in CSS is horrible.  These aren't prohibitive for
normal use and existing browsers don't handle them either, so fixing these
problems or working around them can be put off for now.

<ul>
  <li>Pushing down underlines can change their color, since the color of an
  underline follows the color of the element where it's declared instead of the
  text it's drawn under.  This could be fixed by adding a special case for this
  condition and inserting extra color rules, such as by setting a color on the
  underlining element and then having another element inside it that resets the
  color.  Horrible, but that's text-decoration for you.  Alternatively, the new
  text-decoration-color property in the CSS 3 Text draft could come in handy
  here, in which case we'd degrade pretty gracefully in legacy UAs.

  <li>Underline thickness depends on font-size in all rendering engines but
  WebKit, so pushing them down creates thickness problems as well as color
  problems.  Working around this is a similar story to the previous, except we
  have no text-decoration-width property yet (see <a href=https://lists.w3.org/Archives/Public/www-style/2011Mar/0593.html>www-style
  post</a>).

  <li>The preceding two points can't be avoided, because the only way to remove
  underlines in CSS is to push down styles (unlike most other things where you
  could override it).  Recent (February 2011) CSS 3 Text drafts have added
  support for a "text-decoration-line: cancel-underline" property, but we can
  only use that if there's no other possibility, since it won't work in legacy
  browsers.  (Although we should use it once there's no other possibility.)

  <li>More generally, from a user's perspective, color and thickness of
  underlines is going to be more or less random if they're applying them to
  text with varying size or color.  If they underline a bunch of text all at
  once, it will all get the same color/thickness, probably.  But if they
  underline letter-by-letter, it probably will vary.  But sometimes when they
  underline a bunch of text at once it will also vary, if the algorithm decides
  to create multiple elements for whatever reason (like an intervening
  unwrappable node).  This is unlikely to match user expectations.  There's not
  much we can do about this without entirely revamping text-decoration, so
  we'll have to live with it.

  <li>Currently we don't treat non-underline text-decorations properly, because
  we have no way to set (or cancel) underlines independently of other
  text-decorations from within CSS.  I've sent <a href=https://lists.w3.org/Archives/Public/www-style/2011Mar/0591.html>feedback</a>
  to www-style.
</ul>
</div>

<p><a href=#action>Action</a>: If <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("underline")</a></code> returns true,
<a href="#set-the-selection's-value">set the selection's value</a> to null.  Otherwise <a href="#set-the-selection's-value">set the
selection's value</a> to "underline".  Either way, return true.

<p><a href=#inline-command-activated-values>Inline command activated values</a>: "underline"


<h3 id=the-unlink-command><dfn>The <code title="">unlink</code> command</dfn></h3>

<div class=comments>
<p>IE 9 RC unlinks the whole link you're pointing at, while others only unlink
the current text.  The latter behavior seems less expected, as with createLink,
although I can't articulate precisely why.  Word 2007 and OpenOffice.org 3.2.1
(Ubuntu) seem to give an option to remove the whole link or none of it, which
backs the spec's requirement.  See also #whatwg logs starting at 2011-05-13 at
16:53 EDT (UTC-0400).

<p>See comment for <a href=#the-createlink-command>the <code title="">createLink</code> command</a> about
indeterm/state/value.
</div>

<p><a href=#action>Action</a>:

<ol>
  <li>Let <var title="">hyperlinks</var> be a list of every <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> element that has an
  <code class=external data-anolis-spec=html title=attr-hyperlink-href><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-href>href</a></code> attribute and is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the <a href=#active-range>active range</a> or
  is an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of one of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary points</a>.

  <li><a href=#clear-the-value>Clear the value</a> of each member of <var title="">hyperlinks</var>.

  <li>Return true.
</ol>



<h2 id=block-formatting-commands>Block formatting commands</h2>

<h3 id=block-formatting-command-definitions>Block formatting command definitions</h3>

<p>An <dfn id=indentation-element>indentation element</dfn> is either a <code class=external data-anolis-spec=html title="the blockquote element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-blockquote-element>blockquote</a></code>, or a <code class=external data-anolis-spec=html title="the div element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-div-element>div</a></code>
that has a <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute that sets "margin" or some subproperty of it.

<p class=comments>We need to allow stuff that sets border/padding because
WebKit (Chrome 12 dev) sets "border: none; padding: 0px" when indenting.  We
need to allow stuff that sets classes because WebKit sets
class="webkit-indent-blockquote".  We need to allow stuff that sets dir because
IE9 does.  The criteria could probably be tightened up a bit to reduce false
positives, but it'll do for now.

<p>A <dfn id=simple-indentation-element>simple indentation element</dfn> is an <a href=#indentation-element>indentation
element</a> that has no attributes except possibly

<ul>
  <li>a <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute that sets no properties other than "margin",
  "border", "padding", or subproperties of those; and/or

  <li>a <code class=external data-anolis-spec=html title="the dir attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-dir-attribute>dir</a></code>
  attribute.
</ul>

<p class=note>The notions of indentation element and simple indentation element
parallel those of <a href=#modifiable-element>modifiable element</a> and <a href=#simple-modifiable-element>simple modifiable
element</a>.

<p class=comments>listing and xmp are included because otherwise
insertParagraph inside them won't work, since paragraphs aren't an allowed
child.

<p>A <dfn id=non-list-single-line-container>non-list single-line container</dfn> is an <a href=#html-element>HTML element</a>
with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> "address", "div", "h1", "h2", "h3", "h4", "h5", "h6",
"listing", "p", "pre", or "xmp".

<p>A <dfn id=single-line-container>single-line container</dfn> is either a <a href=#non-list-single-line-container>non-list single-line
container</a>, or an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> "li",
"dt", or "dd".

<p>The <dfn id=block-node-of>block node of</dfn> a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> is either a
<a href=#block-node>block node</a> or null, as returned by the following algorithm:

<ol>
  <li>While <var title="">node</var> is an <a href=#inline-node>inline node</a>, set <var title="">node</var>
  to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>Return <var title="">node</var>.
</ol>

<p class=comments><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14062">Bug 14062</a>.  See
also <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=590640">Mozilla bug
590640</a>, specifically comments 48 and on.

<p>If a <a href=#command>command</a> <dfn id=preserves-overrides>preserves overrides</dfn>, then before taking
its <a href=#action>action</a>, the user agent must <a href=#record-current-overrides>record current
overrides</a>.  After taking the <a href=#action>action</a>, if the <a href=#active-range>active
range</a> is <code class=external data-anolis-spec=dom title=dom-Range-collapsed><a href=http://dom.spec.whatwg.org/#dom-range-collapsed>collapsed</a></code>, it must <a href=#restore-states-and-values>restore states and
values</a> from the recorded list.

<p class=note>All block commands preserve overrides except <a href=#the-inserttext-command>the
<code title="">insertText</code> command</a>, which treats overrides specially.


<h3 id=assorted-block-formatting-command-algorithms>Assorted block formatting command algorithms</h3>

<p class=comments>TODO: When breaking a non-inline element out of an inline
element, like p in b or whatever, it would make sense to re-wrap the contents
in the inline tag.

<p>To <dfn id=fix-disallowed-ancestors>fix disallowed ancestors</dfn> of <var title="">node</var>:

<p class=note>We often run this algorithm after we move a node someplace, just
in case it wound up somewhere it's not supposed to be.  This avoids things like
unserializable DOMs, blocks nested inside inlines, etc.

<ol>
  <li>If <var title="">node</var> is not <a href=#editable>editable</a>, abort these steps.

  <li>
  <p class=comments>This case is really intended to handle stuff like list
  items or table cells that wander outside their proper place.  We generally
  convert them into <code class=external data-anolis-spec=html title="the p element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-p-element>p</a></code>s.

  <p>If <var title="">node</var> is not an <a href=#allowed-child>allowed child</a> of any of its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same editing host</a>:

  <ol>
    <li>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code>, <a href=#wrap>wrap</a> the
    one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of <var title="">node</var>, with <var title="">sibling
    criteria</var> returning true for any <code class=external data-anolis-spec=html title="the dl element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dl-element>dl</a></code> with no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-attribute title=concept-attribute>attributes</a> and
    false otherwise, and <var title="">new parent instructions</var> returning the
    result of calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("dl")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.  Then
    abort these steps.

    <li>
    <p class=comments>There's no reason to change the node to a paragraph if
    that won't make it an allowed child anyway.

    <p>If "p" is not an <a href=#allowed-child>allowed child</a> of the <a href=#editing-host-of>editing host
    of</a> <var title="">node</var>, abort these steps.

    <li>If <var title="">node</var> is not a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>,
    abort these steps.

    <li><a href=#set-the-tag-name>Set the tag name</a> of <var title="">node</var> to the <a href=#default-single-line-container-name>default
    single-line container name</a>, and let <var title="">node</var> be the result.

    <li>
    <p class=comments>Because maybe it somehow wound up as the child of a p,
    like via insertHTML.

    <p><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">node</var>.

    <li>Let <var title="">children</var> be <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>.

    <li>For each <var title="">child</var> in <var title="">children</var>, if <var title="">child</var>
    is a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>:

    <ol>
      <li><a href=#record-the-values>Record the values</a> of the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of
      <var title="">child</var>, and let <var title="">values</var> be the result.

      <li><a href=#split-the-parent>Split the parent</a> of the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of
      <var title="">child</var>.

      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
    </ol>

    <li>Abort these steps.
  </ol>

  <li><a href=#record-the-values>Record the values</a> of the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of
  <var title="">node</var>, and let <var title="">values</var> be the result.

  <li>While <var title="">node</var> is not an <a href=#allowed-child>allowed child</a> of its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>, <a href=#split-the-parent>split the parent</a> of the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting
  of <var title="">node</var>.

  <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
</ol>

<div class=comments>
<p>This algorithm implies that we don't support a sublist in the middle of an
item, only at the end.  For instance,

  <pre>&lt;li&gt;foo&lt;ol&gt;...&lt;/ol&gt;bar&lt;/li&gt;</pre>

<p>gets transformed to

  <pre>&lt;li&gt;foo&lt;/li&gt;&lt;ol&gt;...&lt;/ol&gt;&lt;li&gt;bar&lt;/li&gt;</pre>

<p>which in particular creates an extra list marker for "bar".  This is okay;
we don't need to expose all of HTML's markup abilities through execCommand().
Similarly, the superscript and subscript commands don't allow nesting.  I
didn't see any way to get a sublist in the middle of an item in Word 2007 or in
OpenOffice.org 3.2.1 Ubuntu package, nor in  any browser using just
execCommand(), so it should be no big problem if we require that such nesting
not occur.  (Existing browsers behave weirdly and inconsistently when
confronted with this kind of nesting.)

<p>The reason we need this is that otherwise it gets very confusing to figure out
what happens in cases like trying to outdent
  <pre>&lt;ol&gt;&lt;li&gt;[foo&lt;ol&gt;&lt;li&gt;bar]&lt;/ol&gt;baz&lt;/ol&gt;</pre>
<p>If we first normalize, then the natural answer is something like
  <pre>&lt;p&gt;[foo&lt;ol&gt;&lt;li&gt;bar]&lt;li&gt;baz&lt;/ol&gt;</pre>
<p>but if we don't, we'd have to special-case in the toggle lists and outdent
algorithms.  This might be worthwhile, but it's not at all clear, and what I
have works okay, so I'll stick with it for now.

<p>TODO: Investigate fixing this.
</div>

<p>To <dfn id=normalize-sublists>normalize sublists</dfn> in a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">item</var>:

<ol>
  <li>If <var title="">item</var> is not an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> or it is not <a href=#editable>editable</a> or
  its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not <a href=#editable>editable</a>, abort these steps.

  <li>Let <var title="">new item</var> be null.

  <li>While <var title="">item</var> has an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>:

  <ol>
    <li>Let <var title="">child</var> be the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">item</var>.

    <li>If <var title="">child</var> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, or <var title="">new item</var> is
    null and <var title="">child</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node whose <code class=external data-anolis-spec=domcore title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code>
    consists of zero of more <a class=external data-anolis-spec=encoding href=http://encoding.spec.whatwg.org/#ascii-whitespace title="ascii whitespace">space characters</a>:

    <ol>
      <li>Set <var title="">new item</var> to null.

      <li>Insert <var title="">child</var> into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">item</var>
      immediately following <var title="">item</var>, <a href=#preserving-ranges>preserving ranges</a>.
    </ol>

    <li>Otherwise:

    <ol>
      <li>If <var title="">new item</var> is null, let <var title="">new item</var> be the
      result of calling <code class=external data-anolis-spec=domcore title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("li")</a></code> on the
      <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">item</var>, then insert <var title="">new item</var>
      into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">item</var> immediately after
      <var title="">item</var>.

      <li>Insert <var title="">child</var> into <var title="">new item</var> as its first
      <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, <a href=#preserving-ranges>preserving ranges</a>.
    </ol>
  </ol>
</ol>

<p>The <dfn id="selection's-list-state">selection's list state</dfn> is returned by the following
algorithm:

<div class=note>
<p>This is just a helper to tell the state and indeterminacy of
<a href=#the-insertorderedlist-command>the <code title="">insertOrderedList</code> command</a> and <a href=#the-insertunorderedlist-command>the
<code title="">insertUnorderedList</code> command</a>:

<table>
<tr><th>         <th>ol indeterm <th>ol state <th>ul indeterm <th>ul state
<tr><th>ol       <td>false       <td>true     <td>false       <td>false
<tr><th>ul       <td>false       <td>false    <td>false       <td>true
<tr><th>mixed    <td>true        <td>false    <td>true        <td>false
<tr><th>mixed ol <td>true        <td>false    <td>false       <td>false
<tr><th>mixed ul <td>false       <td>false    <td>true        <td>false
<tr><th>none     <td>false       <td>false    <td>false       <td>false
</table>
</div>

<ol>
  <li>If the <a href=#active-range>active range</a> is null, return "none".

  <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

  <li>For each <var title="">node</var> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var>, append
  <var title="">node</var> to <var title="">node list</var> if the last member of <var title="">node
  list</var> (if any) is not an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
  <var title="">node</var> is <a href=#editable>editable</a>; <var title="">node</var> is not an
  <a href=#indentation-element>indentation element</a>; and <var title="">node</var> is either an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or
  <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, or the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, or an <a href=#allowed-child>allowed
  child</a> of "li".

  <li>If <var title="">node list</var> is empty, return "none".

  <li>
  <div class=comments>
  <p>The child-of-child case is necessary right now because of the following:
    <pre>&lt;ol&gt;&lt;li&gt;[foo&lt;ol&gt;&lt;li&gt;bar]&lt;/ol&gt;baz&lt;/ol&gt;</pre>
  <p>With the current (July 2011) block-extend algorithm, this will become:
    <pre>{&lt;ol&gt;&lt;li&gt;foo&lt;ol&gt;&lt;li&gt;bar&lt;/ol&gt;}baz&lt;/ol&gt;</pre>
  <p>because of the magical li handling in block-extend.  We want this to
  register as ol, because after normalizing sublists it will become
    <pre>{&lt;ol&gt;&lt;li&gt;foo&lt;/li&gt;&lt;ol&gt;&lt;li&gt;bar&lt;/ol&gt;}&lt;li&gt;baz&lt;/ol&gt;</pre>

  <p>But the text node "foo" will wind up in node list, and is not the child of an
  ol.  This is all very messy and has to do with questionable decisions about
  how to handle nested lists.
  </div>

  <p>If every member of <var title="">node list</var> is either an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code>,
  and none is a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> or an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, return "ol".

  <li>
  <p class=comments>This condition and the last are mutually exclusive, so the
  order is actually irrelevant.  Clearly they could only both hold if no member
  of node list is an ol or ul, so if they both held, every member would have to
  be either the child of an ol and of a ul, or of an ol and an li, or a ul and
  an li, or of an li that's the child of both an ol and a ul.  This is
  impossible unless the list is empty, in which case we already aborted.

  <p>If every member of <var title="">node list</var> is either a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> or the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> or the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>,
  and none is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code>, return "ul".

  <li>If some member of <var title="">node list</var> is either an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code>, and some member of <var title="">node list</var> is either a
  <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> or the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> or the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an
  <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, return "mixed".

  <li>If some member of <var title="">node list</var> is either an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code>, return "mixed ol".

  <li>If some member of <var title="">node list</var> is either a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> or the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> or the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>
  of a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, return "mixed ul".

  <li>Return "none".
</ol>

<div class=comments>
<p>When querying the value of justify*, IE9 seems to return boolean false
across the board when it doesn't throw exceptions, which it usually does in my
tests.  Chrome 14 dev returns the string "true" or "false" depending on state,
as in other cases, which is useless.  Opera 11.11 returns "" across the board.
Firefox 6.0a2 behaves like with other command values: it returns
"center"/"justify"/"left"/"right" depending on the active range's start node.
Since this is the only behavior that's possibly useful, it's what I specced.
Firefox ties the value closely to the state, returning true for the state if
and only if the value matches the desired value, but this seems less useful
than what I've specced for the state.

<p>This API is based on the four-state text-align of CSS 2.1.  We do some crude
mapping to make it not break too badly with CSS3 values, but it's not going to
work well given the design of the API.
</div>

<p>The <dfn id=alignment-value>alignment value</dfn> of a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> is returned by
the following algorithm:

<p class=note>This is basically like the resolved value of text-align, but with
two key differences.  First, it only ever evaluates to
center/justify/left/right, since that's the model that the justify commands
work with.  Second, it ignores inline elements, because text-align has no
effect on them and their alignment is actually governed by their nearest block
ancestor (if any).

<ol>
  <li>While <var title="">node</var> is neither null nor an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, or it is an
  <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> but its "display" property has <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> "inline" or "none",
  set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>
  <p class=comments>This means there's no applicable style rule, so probably it
  will wind up left-aligned.  Of course this ignores the fact that the
  alignment will really be "start", so this is wrong for RTL, but it's a pretty
  marginal corner case anyway.  (It will only happen if, e.g., everything up to
  and including the html and body elements have display: inline or none.)

  <p>If <var title="">node</var> is not an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, return "left".

  <li>If <var title="">node</var>'s "text-align" property has <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> "start",
  return "left" if the <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality title="the directionality">directionality</a> of <var title="">node</var> is "ltr", "right"
  if it is "rtl".

  <li>If <var title="">node</var>'s "text-align" property has <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> "end", return
  "right" if the <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality title="the directionality">directionality</a> of <var title="">node</var> is "ltr", "left" if it
  is "rtl".

  <li>If <var title="">node</var>'s "text-align" property has <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> "center",
  "justify", "left", or "right", return that value.

  <li>Return "left".
</ol>

<p class=note>Sometimes one location corresponds to multiple distinct boundary
points.  For instance, in the DOM <code title="">&lt;p&gt;Hello&lt;/p&gt;</code>, a boundary point might
lie at the beginning of the text node or the beginning of the element node, but
these don't logically differ much and will appear the same to the user, so we
often want to treat them the same.  The algorithms here allow navigating
through such equivalent boundary points, for when we want to make the selection
as inclusive or exclusive as possible.  For deletion, we want to delete as few
nodes as possible, so we move the start node forward and the end node backward.
In other cases we might do the reverse, expanding the selection.  In still
other cases we might want to move forward or backward to try getting to a text
node.

<p>Given a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> (<var title="">node</var>, <var title="">offset</var>), the
<dfn id=next-equivalent-point>next equivalent point</dfn> is either a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> or null, as
returned by the following algorithm:

<ol>
  <li>If <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> is zero, return null.

  <li class=note>We don't want to move into or out of zero-length nodes,
  because that would move us straight through them.  For instance, if
  <code title="">{}&lt;span&gt;&lt;/span&gt;</code> were equivalent to <code title="">&lt;span&gt;{}&lt;/span&gt;</code>, it
  would also be equivalent to <code title="">&lt;span&gt;&lt;/span&gt;{}</code>.  This produces very
  unexpected results for nodes like <code title="">&lt;br&gt;</code>.

  <li>If <var title="">offset</var> is <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, and
  <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not null, and <var title="">node</var> is an
  <a href=#inline-node>inline node</a>, return (<var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>, 1 +
  <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>).

  <li class=note>For instance, <code title="">&lt;span&gt;foo[]&lt;/span&gt;</code> is equivalent to
  <code title="">&lt;span&gt;foo{}&lt;/span&gt;</code>, which is equivalent to <code title="">&lt;span&gt;foo&lt;/span&gt;{}</code>.  However, <code title="">&lt;p&gt;foo{}&lt;/p&gt;</code> is <em>not</em> equivalent to
  <code title="">&lt;p&gt;foo&lt;/p&gt;{}</code> &ndash; the cursor might look like it's in a visibly
  different position.

  <li>If <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">offset</var>,
  and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> is not zero, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is an
  <a href=#inline-node>inline node</a>, return (that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, 0).

  <li class=note>For instance, <code title="">{}&lt;span&gt;foo&lt;/span&gt;</code> is equivalent to
  <code title="">&lt;span&gt;{}foo&lt;/span&gt;</code>, which is equivalent to
  <code title="">&lt;span&gt;[]foo&lt;/span&gt;</code>.  As noted before, though, we don't descend into
  empty nodes.  And again, <code title="">{}&lt;p&gt;foo&lt;/p&gt;</code> is different from
  <code title="">&lt;p&gt;{}foo&lt;/p&gt;</code>.

  <li>Return null.
</ol>

<p>Given a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> (<var title="">node</var>, <var title="">offset</var>), the
<dfn id=previous-equivalent-point>previous equivalent point</dfn> is either a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> or null, as
returned by the following algorithm:

<ol>
  <li>If <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> is zero, return null.

  <li>If <var title="">offset</var> is 0, and <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not null,
  and <var title="">node</var> is an <a href=#inline-node>inline node</a>, return (<var title="">node</var>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>, <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>).

  <li>If <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">offset</var>
  &minus; 1, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> is not zero, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is
  an <a href=#inline-node>inline node</a>, return (that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>).

  <li>Return null.
</ol>

<p>The <dfn id=first-equivalent-point>first equivalent point</dfn> of a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>
(<var title="">node</var>, <var title="">offset</var>) is returned by the following algorithm:

<ol>
  <li>While (<var title="">node</var>, <var title="">offset</var>)'s <a href=#previous-equivalent-point>previous equivalent
  point</a> is not null, set (<var title="">node</var>, <var title="">offset</var>) to its
  <a href=#previous-equivalent-point>previous equivalent point</a>.

  <li>Return (<var title="">node</var>, <var title="">offset</var>).
</ol>

<p>The <dfn id=last-equivalent-point>last equivalent point</dfn> of a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a>
(<var title="">node</var>, <var title="">offset</var>) is returned by the following algorithm:

<ol>
  <li>While (<var title="">node</var>, <var title="">offset</var>)'s <a href=#next-equivalent-point>next equivalent
  point</a> is not null, set (<var title="">node</var>, <var title="">offset</var>) to its
  <a href=#next-equivalent-point>next equivalent point</a>.

  <li>Return (<var title="">node</var>, <var title="">offset</var>).
</ol>

<!-- Turned out not to be necessary here, but I've left it in case it turns out
to be handy elsewhere. -->
<!--
<p>Two <span data-anolis-spec=dom title=concept-range-bp>boundary points</span> <var title>A</var> and <var title>B</var> are <dfn>equivalent
boundary points</dfn> if the following algorithm returns true:

<p class=note>This is indeed an <a
href=http://en.wikipedia.org/wiki/Equivalence_relation>equivalence
relation</a>.  Reflexivity, symmetry, and transitivity are all fairly obvious
from the definition.  It also isn't hard to check that using <span>next
equivalent point</span> instead of <span>previous equivalent point</span> would
yield the same definition, because the two algorithms are inverses if neither
output is null.

<ol>
  <li>While <var title>A</var>'s <span>previous equivalent point</span> is not null,
  set <var title>A</var> to its <span>previous equivalent point</span>.

  <li>While <var title>B</var>'s <span>previous equivalent point</span> is not null,
  set <var title>B</var> to its <span>previous equivalent point</span>.

  <li>Return true if <var title>A</var> is the same as <var title>B</var>, otherwise false.
</ol>
-->


<h3 id=block-extending-a-range>Block-extending a range</h3>

<p>A <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> (<var title="">node</var>, <var title="">offset</var>) is a <dfn id=block-start-point>block
start point</dfn> if either <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is null and
<var title="">offset</var> is zero; or <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
<var title="">offset</var> &minus; 1, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is either a
<a href=#visible>visible</a> <a href=#block-node>block node</a> or a <a href=#visible>visible</a> <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>.

<p>A <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> (<var title="">node</var>, <var title="">offset</var>) is a <dfn id=block-end-point>block end
point</dfn> if either <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is null and
<var title="">offset</var> is <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>; or <var title="">node</var> has a
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">offset</var>, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a
<a href=#visible>visible</a> <a href=#block-node>block node</a>.

<p>A <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp title=concept-range-bp>boundary point</a> is a <dfn id=block-boundary-point>block boundary point</dfn> if it is either a
<a href=#block-start-point>block start point</a> or a <a href=#block-end-point>block end point</a>.

<p>When a user agent is to <dfn id=block-extend>block-extend</dfn> a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a>
<var title="">range</var>, it must run the following steps:

<div class=note>
<p>Generally, block commands work on any block that contains part of the
selection, even if the selection doesn't include the whole block.  This
algorithm takes an input range, copies it, stretches out the copy to contain
entire blocks, and returns the result.  Then the caller will normally use it
instead of the range it started with.  For instance, if the cursor is collapsed
in a text node inside a paragraph, this will generally return a range that
includes the whole paragraph.

<p>Two bits of magic worth noting.  First, <code title="">&lt;br&gt;</code> counts as
a block delimiter here, since it looks the same as a block boundary (assuming
no margin etc.) and this is a visual API.  We include the <code title="">&lt;br&gt;</code> as part of the line that precedes it.  Second, if the
selection is inside an <code title="">&lt;li&gt;</code>, this will extend it to
include the whole <code title="">&lt;li&gt;</code>.  This latter point is weird, and
I should re-examine it sometime, but it seems to work.
</div>

<ol>
  <li>Let <var title="">start node</var>, <var title="">start offset</var>, <var title="">end node</var>,
  and <var title="">end offset</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>
  and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offsets</a> of <var title="">range</var>.

  <li>If some <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> of <var title="">start node</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>, set
  <var title="">start offset</var> to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of the last such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> in
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a>, and set <var title="">start node</var> to that <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If (<var title="">start node</var>, <var title="">start offset</var>) is not a <a href=#block-start-point>block
  start point</a>, repeat the following steps:

  <ol>
    <li>If <var title="">start offset</var> is zero, set it to <var title="">start node</var>'s
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">start node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, subtract one from <var title="">start offset</var>.

    <li>If (<var title="">start node</var>, <var title="">start offset</var>) is a <a href=#block-boundary-point>block
    boundary point</a>, break from this loop.
  </ol>

  <li><p class=comments>This just changes something like <code title="">&lt;div&gt;{&lt;p&gt;foo]&lt;/p&gt;&lt;/div&gt;</code> to <code title="">{&lt;div&gt;&lt;p&gt;foo]&lt;/p&gt;&lt;/div&gt;</code>.

  <p>While <var title="">start offset</var> is zero and <var title="">start node</var>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set <var title="">start offset</var> to <var title="">start
  node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">start node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If some <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> of <var title="">end node</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>, set
  <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of the last such <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> in
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a>, and set <var title="">end node</var> to that <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If (<var title="">end node</var>, <var title="">end offset</var>) is not a <a href=#block-end-point>block end
  point</a>, repeat the following steps:

  <ol>
    <li>If <var title="">end offset</var> is <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, set it to
    one plus <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">end node</var> to
    its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, add one to <var title="">end offset</var>.

    <li>If (<var title="">end node</var>, <var title="">end offset</var>) is a <a href=#block-boundary-point>block
    boundary point</a>, break from this loop.
  </ol>

  <li>While <var title="">end offset</var> is <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> and
  <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set <var title="">end offset</var> to
  one plus <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">end node</var> to its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>Let <var title="">new range</var> be a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> and
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offsets</a> are <var title="">start node</var>,
  <var title="">start offset</var>, <var title="">end node</var>, and <var title="">end offset</var>.

  <li>Return <var title="">new range</var>.
</ol>

<p>A <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> <dfn id=follows-a-line-break>follows a line break</dfn> if the following
algorithm returns true:

<ol>
  <li>Let <var title="">offset</var> be zero.

  <li>While (<var title="">node</var>, <var title="">offset</var>) is not a <a href=#block-boundary-point>block boundary
  point</a>:

  <ol>
    <li>If <var title="">node</var> has a <a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var> minus one, return false.

    <li>If <var title="">offset</var> is zero or <var title="">node</var> has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>,
    set <var title="">offset</var> to <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set
    <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var> minus one, then set <var title="">offset</var> to
    <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.
  </ol>

  <li>Return true.
</ol>

<p>A <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> <dfn id=precedes-a-line-break>precedes a line break</dfn> if the following
algorithm returns true:

<ol>
  <li>Let <var title="">offset</var> be <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.

  <li>While (<var title="">node</var>, <var title="">offset</var>) is not a <a href=#block-boundary-point>block boundary
  point</a>:

  <ol>
    <li>If <var title="">node</var> has a <a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var>, return false.

    <li>If <var title="">offset</var> is <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> or <var title="">node</var>
    has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, set <var title="">offset</var> to one plus <var title="">node</var>'s
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var> and set <var title="">offset</var> to zero.
  </ol>

  <li>Return true.
</ol>


<h3 id=recording-and-restoring-overrides>Recording and restoring overrides</h3>
<!--@{-->

<p>To <dfn id=record-current-overrides>record current overrides</dfn>:

<ol>
  <li>Let <var title="">overrides</var> be a list of (string, string or boolean) ordered
  pairs, initially empty.

  <li>
  <div class=comments>
  <p>When restoring, some commands can interfere with others.  Specifically, we
  want to restore createLink before foreColor and underline, and subscript and
  superscript before fontSize.  TODO: This approach only works for default
  styles (although I'm not sure offhand how we could handle non-default styles
  in principle).

  <p>Firefox 7.0a2 and Opera 11.50 don't honor createLink with collapsed
  selections.  If you insert text, it's not linked.  The spec follows Chrome 14
  dev.  IE9 also ignores createLink with collapsed selections, but its behavior
  in other cases for collapsed selections is totally different from all other
  browsers, so it's not a fair comparison.
  </div>

  <p>If there is a <a href=#value-override>value override</a> for "createLink", add
  ("createLink", <a href=#value-override>value override</a> for "createLink") to
  <var title="">overrides</var>.

  <li>
  <p class=comments> Firefox 7.0a2 and Opera 11.50 will honor repeated
  subscript/superscript commands on a collapsed selection, allowing you to nest
  them.  The spec follows the general philosophy that we don't allow users to
  nest subscript/superscript, so the last one wins.  Chrome 14 dev is similar
  to the spec.

  <p>For each <var title="">command</var> in the list "bold", "italic",
  "strikethrough", "subscript", "superscript", "underline", in order: if there
  is a <a href=#state-override>state override</a> for <var title="">command</var>, add
  (<var title="">command</var>, <var title="">command</var>'s <a href=#state-override>state override</a>) to
  <var title="">overrides</var>.

  <li>For each <var title="">command</var> in the list "fontName", "fontSize",
  "foreColor", "hiliteColor", in order: if there is a <a href=#value-override>value
  override</a> for <var title="">command</var>, add (<var title="">command</var>,
  <var title="">command</var>'s <a href=#value-override>value override</a>) to <var title="">overrides</var>.

  <li>Return <var title="">overrides</var>.
</ol>

<p>To <dfn id=record-current-states-and-values>record current states and values</dfn>:

<ol>
  <li>Let <var title="">overrides</var> be a list of (string, string or boolean) ordered
  pairs, initially empty.

  <li>Let <var title="">node</var> be the first <a href=#formattable-node>formattable node</a>
  <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>, or null
  if there is none.

  <li>If <var title="">node</var> is null, return <var title="">overrides</var>.

  <li>Add ("createLink", <var title="">node</var>'s <a href=#effective-command-value>effective command value</a>
  for "createLink") to <var title="">overrides</var>.

  <li>
  <p class=comments>Thus we will set state overrides based on the first
  formattable node, to match values.  This means that if you have
  <code title="">&lt;p&gt;foo&lt;b&gt;[bar&lt;/b&gt;baz]&lt;/p&gt;</code> and hit backspace and hit A, you'll get
  <code title="">&lt;p&gt;foo&lt;b&gt;a[]&lt;/b&gt;&lt;/p&gt;</code>, although bold was previously indeterminate.
  This is needed to match the behavior of hitting A straight away, since
  innerText doesn't strip wrappers when it invokes "delete the contents".

  <p>For each <var title="">command</var> in the list "bold", "italic",
  "strikethrough", "subscript", "superscript", "underline", in order: if
  <var title="">node</var>'s <a href=#effective-command-value>effective command value</a> for <var title="">command</var>
  is one of its <a href=#inline-command-activated-values>inline command activated values</a>, add
  (<var title="">command</var>, true) to <var title="">overrides</var>, and otherwise add
  (<var title="">command</var>, false) to <var title="">overrides</var>.

  <li>For each <var title="">command</var> in the list "fontName", "foreColor",
  "hiliteColor", in order: add (<var title="">command</var>, <var title="">command</var>'s
  <a href=#value>value</a>) to <var title="">overrides</var>.

  <li>
  <p class=comments>Special case for fontSize, because its values are weird.

  <p>Add ("fontSize", <var title="">node</var>'s <a href=#effective-command-value>effective command value</a>
  for "fontSize") to <var title="">overrides</var>.

  <p class=XXX>This is wrong: it will convert non-pixel sizes to pixel sizes.
  But I don't see any way to avoid it.  Hopefully it won't come up too often.
  font-size is a real problem, because the mapping from specified value to
  computed value is lossy and not fully defined (e.g., how many px is
  "small"?).

  <li>Return <var title="">overrides</var>.
</ol>

<p>To <dfn id=restore-states-and-values>restore states and values</dfn> specified by a list
<var title="">overrides</var> returned by the <a href=#record-current-overrides>record current overrides</a> or
<a href=#record-current-states-and-values>record current states and values</a> algorithm:

<ol>
  <li>Let <var title="">node</var> be the first <a href=#formattable-node>formattable node</a>
  <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>, or null
  if there is none.

  <li>If <var title="">node</var> is not null, then for each (<var title="">command</var>,
  <var title="">override</var>) pair in <var title="">overrides</var>, in order:

  <ol>
    <li>If <var title="">override</var> is a boolean, and <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState(<var title="">command</var>)</a></code>
    returns something different from <var title="">override</var>, take the
    <a href=#action>action</a> for <var title="">command</var>, with <var title="">value</var> equal to
    the empty string.

    <li>Otherwise, if <var title="">override</var> is a string, and <var title="">command</var>
    is neither "createLink" nor "fontSize", and <code title=queryCommandValue()><a href=#querycommandvalue()>queryCommandValue(<var title="">command</var>)</a></code>
    returns something not <a href=#equivalent-values title="equivalent values">equivalent</a> to
    <var title="">override</var>, take the <a href=#action>action</a> for <var title="">command</var>,
    with <var title="">value</var> equal to <var title="">override</var>.

    <li>
    <p class=comments>This special case is needed because <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14067">createLink has no
    value</a>.

    <p>Otherwise, if <var title="">override</var> is a string; and <var title="">command</var>
    is "createLink"; and either there is a <a href=#value-override>value override</a> for
    "createLink" that is not equal to <var title="">override</var>, or there is no
    <a href=#value-override>value override</a> for "createLink" and <var title="">node</var>'s
    <a href=#effective-command-value>effective command value</a> for "createLink" is not equal to
    <var title="">override</var>: take the <var title="">action</var> for "createLink", with
    <var title="">value</var> equal to <var title="">override</var>.

    <li>
    <p class=comments>The override will be some CSS value, so we have to
    convert it to a legacy font size.

    <p>Otherwise, if <var title="">override</var> is a string; and <var title="">command</var> is
    "fontSize"; and either there is a <a href=#value-override>value override</a> for
    "fontSize" that is not equal to <var title="">override</var>, or there is no
    <a href=#value-override>value override</a> for "fontSize" and <var title="">node</var>'s
    <a href=#effective-command-value>effective command value</a> for "fontSize" is not
    <a href=#loosely-equivalent-values title="loosely equivalent values">loosely equivalent</a> to <var title="">override</var>:

    <ol>
      <li>Convert <var title="">override</var> to an integer number of pixels, and set
      <var title="">override</var> to the <a href=#legacy-font-size-for>legacy font size for</a> the result.

      <li>Take the <a href=#action>action</a> for "fontSize", with <var title="">value</var>
      equal to <var title="">override</var>.
    </ol>

    <li>Otherwise, continue this loop from the beginning.

    <li>
    <p class=comments>If we took the action for a command, we need to reset
    <var title="">node</var>, because it might have changed.  For instance, if the
    selection was <code title="">foo[bar]baz</code>, the text node could have been split so
    that the first part is now outside the active range.

    <p>Set <var title="">node</var> to the first <a href=#formattable-node>formattable node</a>
    <a href=#effectively-contained>effectively contained</a> in the <a href=#active-range>active range</a>, if
    there is one.
  </ol>

  <li>Otherwise, for each (<var title="">command</var>, <var title="">override</var>) pair in
  <var title="">overrides</var>, in order:

  <ol>
    <li>If <var title="">override</var> is a boolean, set the <a href=#state-override>state
    override</a> for <var title="">command</var> to <var title="">override</var>.

    <li>If <var title="">override</var> is a string, set the <a href=#value-override>value override</a>
    for <var title="">command</var> to <var title="">override</var>.
  </ol>
</ol>

<!--@}-->
<h3 id=deleting-the-selection>Deleting the selection</h3>


<p class=comments>TODO: Consider what should happen for block merging in corner
cases like display: inline-table.

<p>To <dfn id=delete-the-selection>delete the selection</dfn>, given a <var title="">block merging</var> flag
that defaults to true, a <var title="">strip wrappers</var> flag that defaults to
true, and a string <var title="">direction</var> that defaults to "forward":

<div class=note>
<p>The idea behind this algorithm is self-explanatory, but the details wind up
being remarkably complicated.

<p>First, any editable nodes inside the selection will be deleted, and the
selection will be collapsed.  By way of contrast, <a href=#effectively-contained>effectively
contained</a> tries to expand the range to include as much as possible, so
<code title="">&lt;p&gt;[foo]&lt;/p&gt;</code> contains the <code title="">&lt;p&gt;</code>.  What we do here is contract
the range to include as little as possible, so <code title="">{&lt;p&gt;foo&lt;/p&gt;}</code> contains
only <code title="">foo</code> and doesn't delete the paragraph.

<p>After that, if the selection originally started and ended in different
blocks, and the <var title="">block merging</var> flag is true, the end block will get
merged into the start block.  This is needed so if the user selects text on
several lines and deletes it, the text immediately that was before the
selection winds up on the same line as the text immediately after it.  For
example, <code title="">&lt;p&gt;fo[o&lt;/p&gt;&lt;div&gt;b]ar&lt;/div&gt;</code> becomes <code title="">&lt;p&gt;fo[]ar&lt;/p&gt;</code>.
This procedure winds up being tricky, and takes up a large chunk of the logic.

<p>Tables are a notable special case.  If an entire table is contained in the
range, it will be deleted.  If it's anything less, only the contents of the
cells will be deleted and the table structure will be left intact.

<p>The <var title="">strip wrappers</var> flag controls what happens if the deletion
removes all the contents of an inline element.  If wrappers are being stripped,
the empty inline element will be removed: this is usually what you want,
because the user can't position the selection inside it.  But callers like
<a href=#the-inserttext-command>the <code title="">insertText</code> command</a> that intend to
immediately insert new contents want to leave the wrappers, so the new contents
are wrapped by the same thing as the old.

<p>Even if <var title="">strip wrappers</var> is true, the algorithm will set a
<a href=#state-override>state override</a> and <a href=#value-override>value override</a> for any styles it
winds up removing.  This way, if the user deletes a wrapper that adds a style
(or link for that matter), then types something, the new text will get the
style from the old text.
</div>

<ol>
  <li>If the <a href=#active-range>active range</a> is null, abort these steps and do
  nothing.

  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>.

  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a>.

  <li>Let (<var title="">start node</var>, <var title="">start offset</var>) be the <a href=#last-equivalent-point>last
  equivalent point</a> for the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>.

  <li>Let (<var title="">end node</var>, <var title="">end offset</var>) be the <a href=#first-equivalent-point>first
  equivalent point</a> for the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a>.

  <li>If (<var title="">end node</var>, <var title="">end offset</var>) is not <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-after title=concept-range-bp-after>after</a>
  (<var title="">start node</var>, <var title="">start offset</var>):

  <p class=note>This is a selection like
  <code title="">&lt;span&gt;foo[&lt;/span&gt;&lt;/span&gt;]bar&lt;/span&gt;</code>, where the boundary points are
  equivalent but not identical.  We just collapse it and abort, since there's
  nothing to delete.

  <ol>
    <li>If <var title="">direction</var> is "forward", call <code title=dom-Selection-collapseToStart><a href=#dom-selection-collapsetostart>collapseToStart()</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Otherwise, call <code title=dom-Selection-collapseToEnd><a href=#dom-selection-collapsetoend>collapseToEnd()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
    <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Abort these steps.
  </ol>

  <li>If <var title="">start node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and <var title="">start offset</var>
  is 0, set <var title="">start offset</var> to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of <var title="">start node</var>,
  then set <var title="">start node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If <var title="">end node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and <var title="">end offset</var> is
  its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, set <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of
  <var title="">end node</var>, then set <var title="">end node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <p class=note>The previous two steps are so that we won't leave empty text
  nodes anywhere.

  <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on
  the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li class=note>
  <p>When we delete a selection that spans multiple blocks, we merge the end
  block's contents into the start block, like

<pre>&lt;p&gt;fo[o&lt;/p&gt;&lt;pre&gt;b]ar&lt;/pre&gt;
-&gt; &lt;p&gt;fo[]ar&lt;/p&gt;.</pre>

  <p>We figure out what the start and end blocks are before we start deleting
  anything.

  <li>Let <var title="">start block</var> be the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>.

  <li>While <var title="">start block</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#in-the-same-editing-host>in the same editing
  host</a> and <var title="">start block</var> is an <a href=#inline-node>inline node</a>, set
  <var title="">start block</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>
  <div class=comments>
  <p>We only merge to or from block nodes or editing hosts.  (This is just in
  case someone makes a span into an editing host and sticks paragraphs inside
  it or something . . . we could probably drop that proviso.)  Firefox 7.0a2
  ignores the display property when merging, so it doesn't merge <code title="">&lt;span
  style=display:block&gt;</code> but does merge <code title="">&lt;p style=display:inline&gt;</code>.
  This is undesirable, because it's visually wrong.  IE10PP2 and Chrome 14 dev
  behave more like the spec, and Opera 11.50 seems to be unable to make up its
  mind.

  <p>If span isn't an allowed child, it's probably something unpleasant like a
  table row or a list or such.  We don't want to merge to or from something
  like that, because we'd most likely wind up with the wrong type of child
  somewhere.  It should be pretty hard for this to happen given the
  normalization we do on the selection; I'm not actually sure how it could
  happen at all, actually, unless you start out with a DOM that has non-allowed
  children someplace.  So it's basically a sanity check.

  <p>We don't let either start block or end block be a td or th.  This means
  we'll never merge to or from a td or th.  This matches Firefox 5.0a2, and
  reportedly Word as well.  Chrome 13 dev and Opera 11.11 allow merging from a
  non-table cell end block to a table cell start block, but not vice versa.  In
  IE9 the delete key just does nothing.
  </div>

  <p>If <var title="">start block</var> is neither a <a href=#block-node>block node</a> nor an
  <a href=#editing-host>editing host</a>, or "span" is not an <a href=#allowed-child>allowed child</a> of
  <var title="">start block</var>, or <var title="">start block</var> is a <code class=external data-anolis-spec=html title="the td element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-td-element>td</a></code> or <code class=external data-anolis-spec=html title="the th element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-th-element>th</a></code>, set
  <var title="">start block</var> to null.

  <li>Let <var title="">end block</var> be the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end-node title=concept-range-end-node>end node</a>.

  <li>While <var title="">end block</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#in-the-same-editing-host>in the same editing
  host</a> and <var title="">end block</var> is an <a href=#inline-node>inline node</a>, set
  <var title="">end block</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If <var title="">end block</var> is neither a <a href=#block-node>block node</a> nor an
  <a href=#editing-host>editing host</a>, or "span" is not an <a href=#allowed-child>allowed child</a> of
  <var title="">end block</var>, or <var title="">end block</var> is a <code class=external data-anolis-spec=html title="the td element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-td-element>td</a></code> or <code class=external data-anolis-spec=html title="the th element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-th-element>th</a></code>, set
  <var title="">end block</var> to null.

  <li class=note>
  <p>Later on we'll restore <var title="">overrides</var>.  This ensures that
  if we delete inline formatting elements and the user then types something,
  the typed text will have the same style as before.

  <li>
  <div class=comments>
  <p>As far as I can tell, IE9 and Opera 11.50 don't do this at all.  If you
  delete a selection and then start typing, the new text doesn't take on the
  styles of the old text.

  <p>Firefox 7.0a2 seems to do it for some styles but not others.
  Strikethrough, superscript, subscript, and links seem to be lost, at a
  minimum.

  <p>The spec goes with something like Chrome 14 dev, which tries to preserve lots
  of stuff.
  </div>

  <p><a href=#record-current-states-and-values>Record current states and values</a>, and let
  <var title="">overrides</var> be the result.

  <li class=note>
  <p>Now we actually begin deleting things.

  <li>
  <p class=comments>This whole piece of the algorithm is based on
  deleteContents() in DOM Range, copy-pasted and then adjusted to fit.

  <p>If <var title="">start node</var> and <var title="">end node</var> are the same, and
  <var title="">start node</var> is an <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node:

  <ol>
    <li>Call <code class=external data-anolis-spec=dom title=dom-CharacterData-deleteData><a href=http://dom.spec.whatwg.org/#dom-characterdata-deletedata>deleteData(<var title="">start offset</var>, <var title="">end offset</var>
    &minus; <var title="">start offset</var>)</a></code> on <var title="">start node</var>.

    <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at (<var title="">start node</var>,
    <var title="">start offset</var>), with <var title="">fix collapsed space</var> false.

    <li>If <var title="">direction</var> is "forward", call <code title=dom-Selection-collapseToStart><a href=#dom-selection-collapsetostart>collapseToStart()</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Otherwise, call <code title=dom-Selection-collapseToEnd><a href=#dom-selection-collapsetoend>collapseToEnd()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
    <a href=#concept-selection title=concept-selection>selection</a>.

    <li>
    <p class=comments>This is needed to restore any overrides that would
    otherwise be lost.  TODO: In this and similar cases, we could optimize by
    saving only overrides, not the full state/value.

    <p><a href=#restore-states-and-values>Restore states and values</a> from <var title="">overrides</var>.

    <li>Abort these steps.
  </ol>

  <li>If <var title="">start node</var> is an <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, call
  <code class=external data-anolis-spec=dom title=dom-CharacterData-deleteData><a href=http://dom.spec.whatwg.org/#dom-characterdata-deletedata>deleteData()</a></code> on it, with <var title="">start offset</var> as the first argument and
  (<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of <var title="">start node</var> &minus; <var title="">start offset</var>) as
  the second argument.

  <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

  <li>
  <p class=comments>IE9 doesn't seem to let you do any intercell deletions: the
  delete key does nothing if you select across multiple cells.  Firefox 5.0a2
  and Opera 11.11 behave as the spec says, not removing any table things.
  Chrome 13 dev will remove entire rows if selected.  Note that IE, Firefox,
  Word 2007, and OpenOffice.org 3.2.1 Ubuntu all switch to a magic
  cell-selection mode when you try to select between cells, at least in some
  cases, instead of selecting letter-by-letter.

  <p>For each <var title="">node</var> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the <a href=#active-range>active range</a>,
  append <var title="">node</var> to <var title="">node list</var> if the last member of
  <var title="">node list</var> (if any) is not an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
  <var title="">node</var> is <a href=#editable>editable</a>; and <var title="">node</var> is not a
  <code class=external data-anolis-spec=html title="the thead element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-thead-element>thead</a></code>, <code class=external data-anolis-spec=html title="the tbody element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-tbody-element>tbody</a></code>, <code class=external data-anolis-spec=html title="the tfoot element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-tfoot-element>tfoot</a></code>, <code class=external data-anolis-spec=html title="the tr element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-tr-element>tr</a></code>, <code class=external data-anolis-spec=html title="the th element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-th-element>th</a></code>, or <code class=external data-anolis-spec=html title="the td element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-td-element>td</a></code>.

  <li>For each <var title="">node</var> in <var title="">node list</var>:

  <ol>
    <li>Let <var title="">parent</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">node</var>.

    <li>Remove <var title="">node</var> from <var title="">parent</var>.

    <li>
    <p class=comments>Do this before stripping wrappers: see <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13831">bug 13831</a>.

    <p>If the <a href=#block-node-of>block node of</a> <var title="">parent</var> has no
    <a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, and <var title="">parent</var> is
    <a href=#editable>editable</a> or an <a href=#editing-host>editing host</a>, call
    <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and append the result as
    the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">parent</var>.

    <li>
    <p class=comments>Taking insertText to test the case where strip wrappers
    is false, with value a: <code title="">&lt;p&gt;[foo&lt;b&gt;bar&lt;/b&gt;]baz</code> becomes
    <code title="">&lt;p&gt;a[]baz</code> per spec, in IE9, and in Chrome 14 dev.  Firefox 7.0a2
    and Opera 11.50 make it <code title="">&lt;p&gt;a[]&lt;b&gt;&lt;/b&gt;baz</code>, with a useless wrapper.
    <code title="">&lt;p&gt;foo&lt;b&gt;[bar&lt;/b&gt;baz]</code> becomes <code title="">&lt;p&gt;foo&lt;b&gt;a[]&lt;/b&gt;</code> per spec
    and in IE9 and Firefox 7.0a2 and Opera 11.50; in Chrome 14 dev apparently
    it initially becomes <code title="">&lt;p&gt;fooa[]</code>, but then the style is recreated.
    This is detectable if you do something weird like <code title="">&lt;span
    style=color:#aBcDeF&gt;</code> instead of <code title="">&lt;b&gt;</code>: it comes <code title="">&lt;font
    class=Apple-style-span color=#abcdef&gt;</code> or such.  I follow IE9 in all
    cases, because it makes the most sense.

    <p>If <var title="">strip wrappers</var> is true or <var title="">parent</var> is not an
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> of <var title="">start node</var>, while <var title="">parent</var> is
    an <a href=#editable>editable</a> <a href=#inline-node>inline node</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> 0,
    let <var title="">grandparent</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">parent</var>, then
    remove <var title="">parent</var> from <var title="">grandparent</var>, then set
    <var title="">parent</var> to <var title="">grandparent</var>.

    <p class=note>Even if <var title="">strip wrappers</var> is false, we still want to
    strip wrappers that aren't <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestors</a> of <var title="">start node</var>.
    The idea of not stripping wrappers is that we're going to insert new
    content right afterward, like text or an image, but that new content will
    be inserted at the start node.  Wrappers in other places still need to be
    removed, because they would otherwise remain empty.
  </ol>

  <li>If <var title="">end node</var> is an <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, call
  <code class=external data-anolis-spec=dom title=dom-CharacterData-deleteData><a href=http://dom.spec.whatwg.org/#dom-characterdata-deletedata>deleteData(0, <var title="">end offset</var>)</a></code> on it.

  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>, with <var title="">fix collapsed space</var> false.

  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a>, with <var title="">fix collapsed space</var> false.

  <li class=note>
  <p>Now we need to merge blocks.  The simplest case is something like

<pre>&lt;p&gt;fo[o&lt;/p&gt;&lt;p&gt;bar&lt;/p&gt;&lt;p&gt;b]az&lt;/p&gt;
-&gt; &lt;p&gt;fo&lt;/p&gt;{}&lt;p&gt;az&lt;/p&gt;
-&gt; &lt;p&gt;fo{}az&lt;/p&gt;</pre>

  <p>where neither block descends from the other.  More complicated is
  something like

<pre>foo[&lt;p&gt;]bar&lt;/p&gt;
-&gt; foo[]bar</pre>

  <p>or

<pre>&lt;p&gt;foo[&lt;/p&gt;]bar
-&gt; &lt;p&gt;foo[]bar&lt;/p&gt;</pre>

  <p>where one descends from the other.

  <li>If <var title="">block merging</var> is false, or <var title="">start block</var> or
  <var title="">end block</var> is null, or <var title="">start block</var> is not <a href=#in-the-same-editing-host>in the
  same editing host</a> as <var title="">end block</var>, or <var title="">start block</var>
  and <var title="">end block</var> are the same:

  <ol>
    <li>If <var title="">direction</var> is "forward", call <code title=dom-Selection-collapseToStart><a href=#dom-selection-collapsetostart>collapseToStart()</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Otherwise, call <code title=dom-Selection-collapseToEnd><a href=#dom-selection-collapsetoend>collapseToEnd()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
    <a href=#concept-selection title=concept-selection>selection</a>.

    <li><a href=#restore-states-and-values>Restore states and values</a> from <var title="">overrides</var>.

    <li>Abort these steps.
  </ol>

  <li>
  <p class=comments>We might have added a br to the start/end block in an
  earlier step.  Now we're about to merge the blocks, and we don't want the
  br's to get in the way.  The end block is being destroyed no matter what.  If
  the start block winds up empty after merging, we'll add a new br child at the
  end so it doesn't collapse.

  <p>If <var title="">start block</var> has one <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, which is a <a href=#collapsed-block-prop>collapsed
  block prop</a>, remove its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> from it.

  <li>
  <p class=comments>Just repeatedly blow up the end block in this case.

  <p>If <var title="">start block</var> is an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">end block</var>:

  <ol>
    <li>Let <var title="">reference node</var> be <var title="">end block</var>.

    <li>While <var title="">reference node</var> is not a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">start
    block</var>, set <var title="">reference node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>, with
    first argument <var title="">start block</var> and second argument the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of
    <var title="">reference node</var>.

    <li>If <var title="">end block</var> has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>:

    <ol>
      <li>While <var title="">end block</var> is <a href=#editable>editable</a> and is the only
      <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> and is not a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">start
      block</var>, let <var title="">parent</var> equal <var title="">end block</var>, then
      remove <var title="">end block</var> from <var title="">parent</var>, then set <var title="">end
      block</var> to <var title="">parent</var>.

      <li>If <var title="">end block</var> is <a href=#editable>editable</a> and is not an
      <a href=#inline-node>inline node</a>, and its <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> and <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>
      are both <a href=#inline-node title="inline node">inline nodes</a>, call
      <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and insert it into
      <var title="">end block</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> immediately after <var title="">end block</var>.

      <li>If <var title="">end block</var> is <a href=#editable>editable</a>, remove it from its
      <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

      <li><a href=#restore-states-and-values>Restore states and values</a> from <var title="">overrides</var>.

      <li>Abort these steps.
    </ol>

    <li>If <var title="">end block</var>'s <code class=external data-anolis-spec=dom title=dom-Node-firstChild><a href=http://dom.spec.whatwg.org/#dom-node-firstchild>firstChild</a></code> is not an <a href=#inline-node>inline
    node</a>, <a href=#restore-states-and-values>restore states and values</a> from <var title="">record</var>,
    then abort these steps.

    <li>Let <var title="">children</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

    <li>Append the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">end block</var> to
    <var title="">children</var>.

    <li>While <var title="">children</var>'s last member is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, and
    <var title="">children</var>'s last member's <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is an <a href=#inline-node>inline
    node</a>, append <var title="">children</var>'s last member's <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> to
    <var title="">children</var>.

    <li><a href=#record-the-values>Record the values</a> of <var title="">children</var>, and let
    <var title="">values</var> be the result.

    <li>While <var title="">children</var>'s first member's <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not <var title="">start
    block</var>, <a href=#split-the-parent>split the parent</a> of <var title="">children</var>.

    <li>If <var title="">children</var>'s first member's <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> is an
    <a href=#editable>editable</a> <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, remove that <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
  </ol>

  <li>
  <p class=comments>In this case, pull in everything that comes after
  <var title="">start block</var>, until we hit a br or block node.

  <p>Otherwise, if <var title="">start block</var> is a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">end
  block</var>:

  <ol>
    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>, with
    first argument <var title="">start block</var> and second argument <var title="">start
    block</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.

    <li>Let <var title="">reference node</var> be <var title="">start block</var>.

    <li>While <var title="">reference node</var> is not a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">end
    block</var>, set <var title="">reference node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>If <var title="">reference node</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is an <a href=#inline-node>inline
    node</a> and <var title="">start block</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, remove
    <var title="">start block</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> from it.

    <li>Let <var title="">nodes to move</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

    <li>If <var title="">reference node</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is neither null nor a
    <a href=#block-node>block node</a>, append it to <var title="">nodes to move</var>.

    <li>While <var title="">nodes to move</var> is nonempty and its last member isn't a
    <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> and its last member's <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is neither null nor a
    <a href=#block-node>block node</a>, append its last member's <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> to
    <var title="">nodes to move</var>.

    <li><a href=#record-the-values>Record the values</a> of <var title="">nodes to move</var>, and let
    <var title="">values</var> be the result.

    <li>For each <var title="">node</var> in <var title="">nodes to move</var>, append
    <var title="">node</var> as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">start block</var>,
    <a href=#preserving-ranges>preserving ranges</a>.
  </ol>

  <li>
  <p class=comments>In the last case, just move all the children of the end
  block to the start block, and then get rid of any elements we emptied that
  way.

  <p>Otherwise:

  <ol>
    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>, with
    first argument <var title="">start block</var> and second argument <var title="">start
    block</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.

    <li>If <var title="">end block</var>'s <code class=external data-anolis-spec=dom title=dom-Node-firstChild><a href=http://dom.spec.whatwg.org/#dom-node-firstchild>firstChild</a></code> is an <a href=#inline-node>inline node</a>
    and <var title="">start block</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, remove <var title="">start
    block</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> from it.

    <li><a href=#record-the-values>Record the values</a> of <var title="">end block</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>,
    and let <var title="">values</var> be the result.

    <li>While <var title="">end block</var> has <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, append the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>
    of <var title="">end block</var> to <var title="">start block</var>, <a href=#preserving-ranges>preserving
    ranges</a>.

    <li>While <var title="">end block</var> has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, let <var title="">parent</var> be
    the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">end block</var>, then remove <var title="">end block</var> from
    <var title="">parent</var>, then set <var title="">end block</var> to <var title="">parent</var>.
  </ol>

  <li class=note><p>We might have deleted the contents between two lists, in
  which case we should merge them.  See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13976">bug 13976</a>.

  <li>Let <var title="">ancestor</var> be <var title="">start block</var>.

  <li>While <var title="">ancestor</var> has an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> <a href=#in-the-same-editing-host>in
  the same editing host</a> whose <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is also an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> <a href=#in-the-same-editing-host>in
  the same editing host</a>, or an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> <a href=#in-the-same-editing-host>in the
  same editing host</a> whose <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is also a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> <a href=#in-the-same-editing-host>in the
  same editing host</a>:

  <ol>
    <li>While <var title="">ancestor</var> and its <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> are not both <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code>s
    <a href=#in-the-same-editing-host>in the same editing host</a>, and are also not both <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>s
    <a href=#in-the-same-editing-host>in the same editing host</a>, set <var title="">ancestor</var> to its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>While <var title="">ancestor</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> has <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, append
    <var title="">ancestor</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>'s <code class=external data-anolis-spec=dom title=dom-Node-firstChild><a href=http://dom.spec.whatwg.org/#dom-node-firstchild>firstChild</a></code> as the last
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">ancestor</var>, <a href=#preserving-ranges>preserving ranges</a>.

    <li>Remove <var title="">ancestor</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
  </ol>

  <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.

  <li>If <var title="">start block</var> has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, call
  <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and append the result as the
  last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">start block</var>.

  <li><a href=#remove-extraneous-line-breaks-at-the-end-of>Remove extraneous line breaks at the end of</a> <var title="">start
  block</var>.

  <li><a href=#restore-states-and-values>Restore states and values</a> from <var title="">overrides</var>.
</ol>


<h3 id="splitting-a-node-list's-parent">Splitting a node list's parent</h3>

<p>To <dfn id=split-the-parent>split the parent</dfn> of a list <var title="">node list</var> of consecutive
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-sibling title=concept-tree-sibling>sibling</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>:

<div class=note>
<p>This algorithm breaks up the parent of <var title="">node list</var>.  If they're the
only children of their parent, the parent is removed entirely.  If there are
preceding or following siblings, the original parent is left intact as the
parent of those siblings.  If there are both preceding and following siblings,
the original parent is left as the parent of the following siblings and a clone
is used for the parent of the preceding siblings.

<p>We make sure not to disrupt the appearance any more than necessary.
Obviously margins or such on the parent will be lost, but the children will not
wind up on the same line as anything they weren't already on the same line as.
E.g., if we split the parent of "bar" in <code title="">foo&lt;p&gt;bar&lt;/p&gt;</code>, we get <code title="">foo&lt;br&gt;bar</code>, not
<code title="">foobar</code>.  (This is amazingly complicated and error-prone.)
We don't preserve inline styles: callers that want to do that should call
<a href=#record-the-values>record the values</a> and <a href=#restore-the-values>restore the values</a> themselves.

<p>All this is useful in a lot of situations, like for outdenting.  For inline
formatting commands, we almost always rely on <a href=#push-down-values title="push down
values">pushing down values</a> instead, since that often leads to tidier
markup.
</div>

<ol>
  <li>Let <var title="">original parent</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of the first member of
  <var title="">node list</var>.

  <li>If <var title="">original parent</var> is not <a href=#editable>editable</a> or its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is null, do nothing and abort these steps.

  <li>If the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is in <var title="">node
  list</var>, <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a> <var title="">original
  parent</var>.

  <li>If the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is in <var title="">node
  list</var>, and <var title="">original parent</var> <a href=#follows-a-line-break>follows a line break</a>,
  set <var title="">follows line break</var> to true.  Otherwise, set <var title="">follows line
  break</var> to false.

  <li>If the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is in <var title="">node
  list</var>, and <var title="">original parent</var> <a href=#precedes-a-line-break>precedes a line
  break</a>, set <var title="">precedes line break</var> to true.  Otherwise, set
  <var title="">precedes line break</var> to false.

  <li>
  <div class=comments>
  <p>TODO: We insert things after the parent.  This is bad, because it will cause
  them to become part of any ranges that immediately follow.  For instance, if
  we're hitting "bar" in
    <pre>&lt;div&gt;&lt;p&gt;foo&lt;p&gt;bar&lt;/div&gt;{&lt;p&gt;baz}</pre>
  <p>it becomes
    <pre>&lt;div&gt;&lt;p&gt;foo&lt;/div&gt;{&lt;p&gt;bar&lt;p&gt;baz}</pre>
  <p>instead of
    <pre>&lt;div&gt;&lt;p&gt;foo&lt;/div&gt;&lt;p&gt;bar{&lt;p&gt;baz}</pre>
  <p>because of how range mutation rules work.  This doesn't happen if we insert
  before.  This may or may not be important enough to bother working around.
  </div>

  <p>If the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is not in <var title="">node
  list</var>, but its last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is:

  <ol>
    <li>For each <var title="">node</var> in <var title="">node list</var>, <em>in reverse
    order</em>, insert <var title="">node</var> into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original
    parent</var> immediately after <var title="">original parent</var>, <a href=#preserving-ranges>preserving
    ranges</a>.

    <li>If <var title="">precedes line break</var> is true, and the last member of
    <var title="">node list</var> does not <a href=#precedes-a-line-break title="precedes a line break">precede a
    line break</a>, call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and
    insert the result immediately after the last member of <var title="">node
    list</var>.

    <li><a href=#remove-extraneous-line-breaks-at-the-end-of>Remove extraneous line breaks at the end of</a> <var title="">original
    parent</var>.

    <li>Abort these steps.
  </ol>

  <li>If the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is not in <var title="">node
  list</var>:

  <ol>
    <li>Let <var title="">cloned parent</var> be the result of calling <code class=external data-anolis-spec=domcore title=dom-Node-cloneNode><a href=http://dom.spec.whatwg.org/#dom-node-clonenode>cloneNode(false)</a></code>
    on <var title="">original parent</var>.

    <li>If <var title="">original parent</var> has an <code class=external data-anolis-spec=html title="the id attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-id-attribute>id</a></code> attribute, unset it.

    <li>Insert <var title="">cloned parent</var> into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original
    parent</var> immediately before <var title="">original parent</var>.

    <li>While the <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> of the first member of <var title="">node
    list</var> is not null, append the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">original
    parent</var> as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">cloned parent</var>,
    <a href=#preserving-ranges>preserving ranges</a>.
  </ol>

  <li>
  <p class=comments>Notice that a boundary point that was immediately before
  the element will now be immediately before its children, just because of the
  regular range mutation rules, without needing to worry about preserving
  ranges.  Likewise for boundary points immediately after the element, if we
  wind up removing the element in the final step.  Preserving ranges is only
  necessary for the sake of boundary points in the element or its descendants.

  <p>For each <var title="">node</var> in <var title="">node list</var>, insert <var title="">node</var>
  into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">original parent</var> immediately before
  <var title="">original parent</var>, <a href=#preserving-ranges>preserving ranges</a>.

  <li>If <var title="">follows line break</var> is true, and the first member of
  <var title="">node list</var> does not <a href=#follows-a-line-break title="follows a line break">follow a
  line break</a>, call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and
  insert the result immediately before the first member of <var title="">node
  list</var>.

  <li>If the last member of <var title="">node list</var> is an <a href=#inline-node>inline node</a>
  other than a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, and the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> is
  a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, and <var title="">original parent</var> is not an <a href=#inline-node>inline node</a>,
  remove the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">original parent</var> from <var title="">original
  parent</var>.

  <li>If <var title="">original parent</var> has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>:

  <ol>
    <li>Remove <var title="">original parent</var> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>If <var title="">precedes line break</var> is true, and the last member of
    <var title="">node list</var> does not <a href=#precedes-a-line-break title="precedes a line break">precede a
    line break</a>, call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and
    insert the result immediately after the last member of <var title="">node
    list</var>.
  </ol>

  <li>Otherwise, <a href=#remove-extraneous-line-breaks-before>remove extraneous line breaks before</a>
  <var title="">original parent</var>.

  <li>
  <p class=comments>The parent might be null if it's a br that we removed in
  the last step, in which case this step isn't necessary.

  <p>If <var title="">node list</var>'s last member's <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is null,
  but its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not null, <a href=#remove-extraneous-line-breaks-at-the-end-of>remove extraneous line breaks at the
  end of</a> <var title="">node list</var>'s last member's <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
</ol>

<p>To remove a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> while <dfn id=preserving-its-descendants>preserving its
descendants</dfn>, <a href=#split-the-parent>split the parent</a> of <var title="">node</var>'s
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> if it has any.  If it has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, instead remove it from
its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.


<h3 id=canonical-space-sequences>Canonical space sequences</h3>

<div class=note>
<p>Whitespace in HTML normally collapses.  However, if the user hits the space
bar twice in an HTML editor, they expect to see two spaces, not one.  Even if
they hit the space bar once at the beginning or end of a line, it would
collapse without special handling.  The only good solution here is for the
author to set white-space: pre-wrap on the editable area, and on everywhere the
content is reproduced.  But if they don't, we have to painfully hack around the
problem.

<p>This is a basically intractable problem because of the unfortunate
confluence of three factors.  One, our characters are Unicode, and Unicode
doesn't know about whitespace collapsing, so it provides no special characters
to control it.  Two, HTML itself provides no features that control whitespace
collapsing without undesired side effects (like inhibiting line breaks or not
being allowed inside <code title="">&lt;p&gt;</code>).  Three, we need to support
user agents that don't reliably support CSS, since that includes many popular
mail clients.

<p>The upshot is we have no good way to control whitespace collapse, so we rely
on the least bad way available: <code title="">&amp;nbsp;</code>.  This doesn't
collapse with adjacent whitespace in browsers, which is good.  But it also
doesn't allow a line break opportunity, which is bad.  In any run of whitespace
that we don't want to collapse, any two regular spaces must be separated by an
<code title="">&amp;nbsp;</code> so they don't collapse together, but we need to
carefully limit runs of consecutive <code title="">&amp;nbsp;</code>s to minimize
the damage to line-breaking behavior.

<p>The result is an elaborate and meticulously-crafted hodgepodge of bad
compromises that frankly isn't worth the effort to explain here.  The saving
grace is that it all gets disabled if white-space is set to pre-wrap as it
should be, so authors can opt out of the insanity.  Interested readers will
find detailed rationale for the exact sequences required in the comments.
</div>

<p class=comments>See long comment before <a href=#the-inserttext-command>insertText</a>.

<p>The <dfn id=canonical-space-sequence>canonical space sequence</dfn> of length <var title="">n</var>, with boolean
flags <var title="">non-breaking start</var> and <var title="">non-breaking end</var>, is
returned by the following algorithm:

<ol>
  <li>If <var title="">n</var> is zero, return the empty string.

  <li>If <var title="">n</var> is one and both <var title="">non-breaking start</var> and
  <var title="">non-breaking end</var> are false, return a single space (U+0020).

  <li>If <var title="">n</var> is one, return a single non-breaking space (U+00A0).

  <li>Let <var title="">buffer</var> be the empty string.

  <li>If <var title="">non-breaking start</var> is true, let <var title="">repeated pair</var> be
  U+00A0 U+0020.  Otherwise, let it be U+0020 U+00A0.

  <li>While <var title="">n</var> is greater than three, append <var title="">repeated pair</var>
  to <var title="">buffer</var> and subtract two from <var title="">n</var>.

  <li>If <var title="">n</var> is three, append a three-<a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> string to
  <var title="">buffer</var> depending on <var title="">non-breaking start</var> and
  <var title="">non-breaking end</var>:

  <dl class=switch>
    <dt><var title="">non-breaking start</var> and <var title="">non-breaking end</var> false
    <dd>U+0020 U+00A0 U+0020

    <dt><var title="">non-breaking start</var> true, <var title="">non-breaking end</var> false
    <dd>U+00A0 U+00A0 U+0020

    <dt><var title="">non-breaking start</var> false, <var title="">non-breaking end</var> true
    <dd>U+0020 U+00A0 U+00A0

    <dt><var title="">non-breaking start</var> and <var title="">non-breaking end</var> both true
    <dd>U+00A0 U+0020 U+00A0
  </dl>

  <li>Otherwise, append a two-<a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> string to <var title="">buffer</var> depending
  on <var title="">non-breaking start</var> and <var title="">non-breaking end</var>:

  <dl class=switch>
    <dt><var title="">non-breaking start</var> and <var title="">non-breaking end</var> false
    <dt><var title="">non-breaking start</var> true, <var title="">non-breaking end</var> false
    <dd>U+00A0 U+0020

    <dt><var title="">non-breaking start</var> false, <var title="">non-breaking end</var> true
    <dd>U+0020 U+00A0

    <dt><var title="">non-breaking start</var> and <var title="">non-breaking end</var> both true
    <dd>U+00A0 U+00A0
  </dl>

  <li>Return <var title="">buffer</var>.
</ol>

<p>To <dfn id=canonicalize-whitespace>canonicalize whitespace</dfn> at (<var title="">node</var>,
<var title="">offset</var>), given an optional boolean argument <var title="">fix collapsed
space</var> that defaults to true:

<ol>
  <li>If <var title="">node</var> is neither <a href=#editable>editable</a> nor an <a href=#editing-host>editing
  host</a>, abort these steps.

  <li>Let <var title="">start node</var> equal <var title="">node</var> and let <var title="">start
  offset</var> equal <var title="">offset</var>.

  <li>
  <p class=comments>First we go to the beginning of the current whitespace run.

  <p>Repeat the following steps:

  <ol>
    <li>If <var title="">start node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> <a href=#in-the-same-editing-host>in the same editing
    host</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start offset</var> minus one, set
    <var title="">start node</var> to that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, then set <var title="">start offset</var>
    to <var title="">start node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.

    <li>
    <p class=comments>TODO: Following a line break is unlikely to be the right
    criterion.

    <p>Otherwise, if <var title="">start offset</var> is zero and <var title="">start node</var>
    does not <a href=#follows-a-line-break title="follows a line break">follow a line break</a> and
    <var title="">start node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#in-the-same-editing-host>in the same editing
    host</a>, set <var title="">start offset</var> to <var title="">start node</var>'s
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">start node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, if <var title="">start node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>'s <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> for "white-space" is neither "pre" nor "pre-wrap"
    and <var title="">start offset</var> is not zero and the (<var title="">start offset</var>
    &minus; 1)st <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> of <var title="">start node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> is a space
    (0x0020) or non-breaking space (0x00A0), subtract one from <var title="">start
    offset</var>.

    <li>Otherwise, break from this loop.
  </ol>

  <li>
  <p class=comments>Now we collapse any consecutive spaces, if <var title="">fix
  collapsed space</var> is true.

  <p>Let <var title="">end node</var> equal <var title="">start node</var> and <var title="">end
  offset</var> equal <var title="">start offset</var>.

  <li>Let <var title="">length</var> equal zero.

  <li>
  <p class=comments>This tries to delete spaces at the beginning of a line (<a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14119">bug 14119</a>).

  <p>Let <var title="">collapse spaces</var> be true if <var title="">start offset</var> is zero
  and <var title="">start node</var> <a href=#follows-a-line-break>follows a line break</a>, otherwise false.

  <li>Repeat the following steps:

  <ol>
    <li>If <var title="">end node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> <a href=#in-the-same-editing-host>in the same editing
    host</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end offset</var>, set <var title="">end node</var>
    to that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, then set <var title="">end offset</var> to zero.

    <li>
    <p class=comments>TODO: Preceding a line break is unlikely to be the right
    criterion.

    <p>Otherwise, if <var title="">end offset</var> is <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>
    and <var title="">end node</var> does not <a href=#precedes-a-line-break title="precedes a line
    break">precede a line break</a> and <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is
    <a href=#in-the-same-editing-host>in the same editing host</a>, set <var title="">end offset</var> to one
    plus <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">end node</var> to its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, if <var title="">end node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>'s <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> for "white-space" is neither "pre" nor "pre-wrap"
    and <var title="">end offset</var> is not <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> and the
    <var title="">end offset</var>th <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> of <var title="">end node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> is a
    space (0x0020) or non-breaking space (0x00A0):

    <ol>
      <li>If <var title="">fix collapsed space</var> is true, and <var title="">collapse
      spaces</var> is true, and the <var title="">end offset</var>th <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> of
      <var title="">end node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> is a space (0x0020): call
      <code class=external data-anolis-spec=dom title=dom-CharacterData-deleteData><a href=http://dom.spec.whatwg.org/#dom-characterdata-deletedata>deleteData(<var title="">end offset</var>, 1)</a></code> on <var title="">end node</var>, then
      continue this loop from the beginning.

      <li>Set <var title="">collapse spaces</var> to true if the <var title="">end offset</var>th
      <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> of <var title="">end node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> is a space (0x0020),
      false otherwise.

      <li>Add one to <var title="">end offset</var>.

      <li>Add one to <var title="">length</var>.
    </ol>

    <li>Otherwise, break from this loop.
  </ol>

  <li>
  <p class=comments>We've already stripped leading whitespace, and collapsed
  consecutive spaces.  Now we try to strip any collapsed trailing whitespace
  (<a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=14119">bug 14119</a>
  again).

  <p>If <var title="">fix collapsed space</var> is true, then while (<var title="">start
  node</var>, <var title="">start offset</var>) is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-before title=concept-range-bp-before>before</a> (<var title="">end node</var>,
  <var title="">end offset</var>):

  <ol>
    <li>If <var title="">end node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> <a href=#in-the-same-editing-host>in the same editing
    host</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end offset</var> &minus; 1, set <var title="">end
    node</var> to that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, then set <var title="">end offset</var> to <var title="">end
    node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.

    <li>Otherwise, if <var title="">end offset</var> is zero and <var title="">end node</var>'s
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#in-the-same-editing-host>in the same editing host</a>, set <var title="">end
    offset</var> to <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">end
    node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, if <var title="">end node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>'s <a href=http://dev.w3.org/csswg/cssom/#resolved-value>resolved value</a> for "white-space" is neither "pre" nor "pre-wrap"
    and <var title="">end offset</var> is <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> and the last
    <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> of <var title="">end node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> is a space (0x0020) and
    <var title="">end node</var> <a href=#precedes-a-line-break>precedes a line break</a>:

    <ol>
      <li>Subtract one from <var title="">end offset</var>.

      <li>Subtract one from <var title="">length</var>.

      <li>Call <code class=external data-anolis-spec=dom title=dom-CharacterData-deleteData><a href=http://dom.spec.whatwg.org/#dom-characterdata-deletedata>deleteData(<var title="">end offset</var>, 1)</a></code> on <var title="">end node</var>.
    </ol>

    <li>Otherwise, break from this loop.
  </ol>

  <li>
  <p class=comments>Finally we replace with the canonical sequence.

  <p>Let <var title="">replacement whitespace</var> be the <a href=#canonical-space-sequence>canonical space
  sequence</a> of length <var title="">length</var>.  <var title="">non-breaking start</var>
  is true if <var title="">start offset</var> is zero and <var title="">start node</var>
  <a href=#follows-a-line-break>follows a line break</a>, and false otherwise.  <var title="">non-breaking
  end</var> is true if <var title="">end offset</var> is <var title="">end node</var>'s
  <code class=external data-anolis-spec=dom title=dom-CharacterData-length><a href=http://dom.spec.whatwg.org/#dom-characterdata-length>length</a></code> and <var title="">end node</var> <a href=#precedes-a-line-break>precedes a line break</a>, and
  false otherwise.

  <li>While (<var title="">start node</var>, <var title="">start offset</var>) is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-before title=concept-range-bp-before>before</a>
  (<var title="">end node</var>, <var title="">end offset</var>):

  <ol>
    <li>If <var title="">start node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start
    offset</var>, set <var title="">start node</var> to that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, then set
    <var title="">start offset</var> to zero.

    <li>Otherwise, if <var title="">start node</var> is not a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node or if
    <var title="">start offset</var> is <var title="">start node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, set
    <var title="">start offset</var> to one plus <var title="">start node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then
    set <var title="">start node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise:

    <ol>
      <li>Remove the first <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> from <var title="">replacement whitespace</var>,
      and let <var title="">element</var> be that <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a>.

      <li>If <var title="">element</var> is not the same as the <var title="">start
      offset</var>th <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> of <var title="">start node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code>:

      <ol>
        <li>
        <p class=comments>We need to insert then delete, so that we don't
        change range boundary points.  TODO: switch to using "replace data" now
        that DOM Core has defined that.

        <p>Call <code class=external data-anolis-spec=dom title=dom-CharacterData-insertData><a href=http://dom.spec.whatwg.org/#dom-characterdata-insertdata>insertData(<var title="">start offset</var>, <var title="">element</var>)</a></code> on
        <var title="">start node</var>.

        <li>Call <code class=external data-anolis-spec=dom title=dom-CharacterData-deleteData><a href=http://dom.spec.whatwg.org/#dom-characterdata-deletedata>deleteData(<var title="">start offset</var> + 1, 1)</a></code> on
        <var title="">start node</var>.
      </ol>

      <li>Add one to <var title="">start offset</var>.
    </ol>
  </ol>
</ol>


<h3 id=indenting-and-outdenting>Indenting and outdenting</h3>

<div class=note>
<p>There are two basically different types of indent/outdent: lists, and
everything else.  For lists we'll wrap the item in a nested list to indent, and
<a href=#split-the-parent title="split the parent">split its parent</a> to outdent.  For
everything else we'll wrap in a <code title="">&lt;blockquote&gt;</code> to indent,
and try breaking it out of an ancestor <a href=#indentation-element>indentation element</a> to
outdent.

<p>Indenting winds up being pretty simple: just add an appropriate wrapper.
There's not really anything to think about here except which wrapper we want
(<code title="">&lt;ol&gt;</code> or <code title="">&lt;ul&gt;</code> or <code title="">&lt;blockquote&gt;</code>), and establishing that is not rocket science.

<p>Outdenting is considerably more complicated.  The basic idea we follow is to
first find the nearest editable ancestor that's a list or <a href=#indentation-element>indentation
element</a>.  If we succeed, and the node we're trying to outdent is the
only descendant of the ancestor, of course we can just remove the ancestor and
that's that.  Otherwise, what we do is remove the ancestor and then indent all
its other descendants, much like <a href=#push-down-values title="push down values">pushing down
values</a>.

<p>But of course, there are complications.  We don't always actually want to
remove the <em>closest</em> ancestor that's causing indentation.  For one
thing, we prefer ancestors that we can remove completely, i.e., <a href=#simple-indentation-element title="simple indentation element">simple indentation elements</a>.  When
outdenting <code title="">&lt;blockquote&gt;&lt;blockquote
id="abc"&gt;foo&lt;/blockquote&gt;&lt;/blockquote&gt;</code>, removing the inner tag
would result in <code title="">&lt;blockquote&gt;&lt;div
id="abc"&gt;foo&lt;/div&gt;&lt;/blockquote&gt;</code>, since we don't want to lose the
id.  Thus we prefer to remove the outer tag and wind up with <code title="">&lt;blockquote id="abc"&gt;foo&lt;/blockquote&gt;</code>.

<p>Also, if the node we're outdenting is itself a list, we prefer to remove an
ancestor <a href=#indentation-element>indentation element</a> rather than the list.  Otherwise, if
the user selected some text, indented it, then added a list, there would be no
way to remove the indentation without removing the list first.  This way, the
user could remove the list with the appropriate list-toggling command or remove
the indentation with the outdent command.
</div>

<div class=comments>
<p>We have to handle entire lists of siblings at once, or else we'd wind up
doing something like

<pre>&lt;ol&gt;
  {&lt;li&gt;foo&lt;/li&gt;
  &lt;ol&gt;&lt;li&gt;bar&lt;/li&gt;&lt;/ol&gt;}
&lt;/ol&gt;
-&gt;
&lt;ol&gt;&lt;ol&gt;
  &lt;li&gt;foo&lt;/li&gt;
  &lt;li&gt;bar&lt;/li&gt;
&lt;/ol&gt;&lt;/ol&gt;
-&gt;
&lt;ol&gt;&lt;ol&gt;&lt;ol&gt;
  &lt;li&gt;foo&lt;/li&gt;
  &lt;li&gt;bar&lt;/li&gt;
&lt;/ol&gt;&lt;/ol&gt;&lt;/ol&gt;</pre>

<p>since by the time we got to doing the &lt;ol&gt; that originally contained
"bar", we won't remember that we aren't supposed to indent "foo" a second time.
</div>

<p>To <dfn id=indent>indent</dfn> a list <var title="">node list</var> of consecutive <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-sibling title=concept-tree-sibling>sibling</a>
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>:

<ol>
  <li>If <var title="">node list</var> is empty, do nothing and abort these steps.

  <li>Let <var title="">first node</var> be the first member of <var title="">node list</var>.

  <li>If <var title="">first node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>:

  <ol>
    <li>Let <var title="">tag</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> of the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of
    <var title="">first node</var>.

    <li>
    <div class=comments>
    <p>This matches IE9, Firefox 4.0, and Chrome 12 dev.  If there's a
    preceding &lt;li&gt;, Opera 11.10 instead adds the new parent to the end of
    that &lt;li&gt;, so it's not the child of another list, which is invalid.  But
    the other browsers' way of doing things makes things simpler.  E.g., if we
    want to indent an &lt;li&gt; and it has &lt;ol&gt;/&lt;ul&gt; children, we have to
    distinguish between the case where we want to indent the whole &lt;li&gt; or
    only the first part.  It also allows things like

<pre>&lt;ol&gt;&lt;li&gt;
  foo
  &lt;ol&gt;&lt;li&gt;bar&lt;/li&gt;&lt;/ol&gt;
  baz
&lt;/li&gt;&lt;/ol&gt;</pre>

    <p>in which case it's unclear what we should do if the user selects "foo" and
    indents.  I've filed <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=12609">a bug</a> on
    HTML5.
    </div>

    <p><a href=#wrap>Wrap</a> <var title="">node list</var>, with <var title="">sibling criteria</var>
    returning true for an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a>
    <var title="">tag</var> and false otherwise, and <var title="">new parent
    instructions</var> returning the result of calling
    <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">tag</var>)</a></code> on the <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">first
    node</var>.

    <li>Abort these steps.
  </ol>

  <li>
  <div class=comments>
  <p>Firefox 4.0 respects the CSS styling flag for indent, but Chrome 12 dev
  does not.  I always produce blockquotes, even if CSS styling is on, for two
  reasons.  One, IE9 handles inline margin attributes badly: when outdenting,
  it propagates the margin to the parent, which doesn't actually remove it.
  Two, in CSS mode I'd want to use &lt;div style="margin: 1em 40px"&gt; to match
  non-CSS mode, but authors are very likely to want to remove the top/bottom
  margin, which they can't do if it's not a special tag.  Authors who really
  want divs for indentation could always convert the blockquotes to divs
  themselves.  But if people really want it, I could respect CSS styling mode
  here too.

  <p>The top/bottom margins might be undesirable here, but no more so than for
  &lt;ol&gt;/&lt;ul&gt;/&lt;p&gt;/etc.  Here as there, authors can remove them with CSS
  if they want.

  <p>blockquote indents on both sides, so we don't have to worry about
  directionality.  In theory it would be better if we indented only on the
  start side, but that requires care to get right in mixed-direction cases.
  Even once browsers start to support margin-start and so on, we can't use them
  because a) we have to work okay in legacy browsers and b) it doesn't help if
  a descendant block has different direction (so should be indented the other
  way).  So let's not worry about it: most browsers don't, and the ones that do
  get it wrong.  Just indent on both sides.
  </div>

  <p><a href=#wrap>Wrap</a> <var title="">node list</var>, with <var title="">sibling criteria</var>
  returning true for a <a href=#simple-indentation-element>simple indentation element</a> and false
  otherwise, and <var title="">new parent instructions</var> returning the result of
  calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("blockquote")</a></code> on the <code class=external data-anolis-spec=dom title=dom-Node-ownerDocument><a href=http://dom.spec.whatwg.org/#dom-node-ownerdocument>ownerDocument</a></code> of <var title="">first
  node</var>.  Let <var title="">new parent</var> be the result.

  <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">new parent</var>.
</ol>

<div class=comments>
<p>Things that are produced for indentation that we need to consider removing:

<ul>
  <li>Plain &lt;blockquote&gt; (produced by spec, Firefox 4.0 non-CSS, Opera
  11.00)

  <li>&lt;blockquote style="margin-right: 0" dir="ltr"&gt; and &lt;blockquote
  style="margin-left: 0" dir="rtl"&gt; (IE9)

  <li>&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0
  40px; border: none; padding: 0px"&gt; (Chrome 12 dev)

  <li>&lt;div style="margin-left: 40px"&gt; and &lt;div style="margin-right:
  40px"&gt; (Firefox 4.0 CSS if no other element available)

  <li>Other random things with display: block whose left or right margin was
  increased by 40px (Firefox 4.0 CSS)
</ul>

<p>For discussion on the list-related stuff, see the comment for
<a href=#the-insertorderedlist-command>insertOrderedList</a>.

<p>Gecko in CSS mode just adds margin properties to random elements that are
lying around.  We don't attempt to remove those, because 1) the amount and
position of the margin can vary (it increases the margin if there's a
preexisting one), so it's potentially complicated, and 2) no browser removes
such margins on outdent, including Gecko, except for Gecko in CSS mode.  TODO:
Consider removing it anyway.
</div>

<p>To <dfn id=outdent>outdent</dfn> a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var>:

<ol>
  <li>If <var title="">node</var> is not <a href=#editable>editable</a>, abort these steps.

  <li>
  <p class=comments>The easy case is when the whole element is indented.  In
  this case we remove the whole thing indiscriminately.  In the case of
  blockquotes created by IE, this might change the direction of some children,
  but then their direction was probably changed incorrectly in the first place,
  so no harm.

  <p>If <var title="">node</var> is a <a href=#simple-indentation-element>simple indentation element</a>, remove
  <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.  Then abort these
  steps.

  <li>
  <p class=comments>This might be a simple indentation element that had style
  added to it by Firefox in CSS mode, for instance (color, font-family, etc.).

  <p>If <var title="">node</var> is an <a href=#indentation-element>indentation element</a>:

  <ol>
    <li>Unset the <code class=external data-anolis-spec=html title="the dir
    attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-dir-attribute>dir</a></code> attribute of <var title="">node</var>, if any.

    <li>Unset the margin, padding, and border CSS properties of
    <var title="">node</var>.

    <li><a href=#set-the-tag-name>Set the tag name</a> of <var title="">node</var> to "div".

    <li>Abort these steps.
  </ol>

  <li>
  <div class=comments>
  <p>Approximate algorithms when an ancestor is causing the indentation appear
  to be:

  <dl>
    <dt>IE9
    <dd>Go to the innermost element causing indentation.  If the stuff to be
    outdented includes all the contents of that element, get rid of it, but if
    it has any attributes, change it to a &lt;p&gt; with those same attributes.  This
    is an excellent idea in general, but unfortunately it preserves
    explicitly-specified margins in style attributes, which isn't great.  In
    other cases, it moves the stuff to be outdented outside.  Not clear on
    all the details, seems to be pretty confusing.  Also does a bunch of
    seemingly arbitrary normalization like removing divs and some attributes
    from some things . . .

    <dt>Firefox 4.0
    <dd>Go to the innermost element causing indentation.  If the stuff to be
    outdented includes all the contents of that element, get rid of it, even if
    it has arbitrary attributes.  Otherwise, move the stuff to be outdented
    outside the indenting element.  If there are any intervening elements that
    include stuff not to be outdented, wrap the outdented stuff in copies
    (which can duplicate id's, etc.).

    <dt>Chrome 12 dev
    <dd>Go to the outermost element causing indentation (even if the current
    element is itself causing indentation).  Move the text to be outdented
    outside that outermost element, without regard to any intervening elements.
    Then recreate the original styles on the moved text, in some fashion.
    Something like that; it confuses me and doesn't seem to be reasonable.

    <dt>Opera 11.00
    <dd>Like Firefox, except it goes to the outermost element, not the
    innermost.  Also seems to special-case to avoid duplicate id's, and has a
    few other quirks.
  </dl>

  <p>Overall, all flawed, so I'll make up my own, patterned after pushing down
  styles.  First we search ancestors for a simple indentation element, which we
  stand a chance of completely removing.  Failing that, we look for an
  indentation element that's not simple, so we can't completely remove it.
  </div>

  <p>Let <var title="">current ancestor</var> be <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>Let <var title="">ancestor list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

  <li>While <var title="">current ancestor</var> is an <a href=#editable>editable</a> <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>
  that is neither a <a href=#simple-indentation-element>simple indentation element</a> nor an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> nor a
  <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, append <var title="">current ancestor</var> to <var title="">ancestor list</var> and
  then set <var title="">current ancestor</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If <var title="">current ancestor</var> is not an <a href=#editable>editable</a>
  <a href=#simple-indentation-element>simple indentation element</a>:

  <ol>
    <li>Let <var title="">current ancestor</var> be <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Let <var title="">ancestor list</var> be the empty list.

    <li>While <var title="">current ancestor</var> is an <a href=#editable>editable</a>
    <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> that is neither an <a href=#indentation-element>indentation element</a> nor an
    <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> nor a <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, append <var title="">current ancestor</var> to <var title="">ancestor
    list</var> and then set <var title="">current ancestor</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
  </ol>

  <li>
  <p class=comments>When asked to outdent a list wrapped in a simple
  indentation element, Chrome 12 dev removes the list instead of the simple
  indentation element.  Opera 11.10 seems to remove both.  IE9 and Firefox 4.0
  remove the simple indentation element, as does the spec.

  <p>If <var title="">node</var> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> and <var title="">current ancestor</var>
  is not an <a href=#editable>editable</a> <a href=#indentation-element>indentation element</a>:

  <ol>
    <li>Unset the <code class=external data-anolis-spec=html title=attr-ol-reversed><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#attr-ol-reversed>reversed</a></code>, <code class=external data-anolis-spec=html title=attr-ol-start><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#attr-ol-start>start</a></code>, and <code class=external data-anolis-spec=html title=attr-ol-type><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#attr-ol-type>type</a></code> attributes of <var title="">node</var>, if any are
    set.

    <li>Let <var title="">children</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> of <var title="">node</var>.

    <li>
    <p class=comments>We can't turn it into a div if it's the child of an ol or
    ul, because that's not allowed: there's no way to group li's (see
    <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13128">HTML bug 13128</a>).

    <p>If <var title="">node</var> has attributes, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code>
    or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">node</var> to "div".

    <li>Otherwise:

    <ol>
      <li><a href=#record-the-values>Record the values</a> of <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, and
      let <var title="">values</var> be the result.

      <li>Remove <var title="">node</var>, <a href=#preserving-its-descendants>preserving its descendants</a>.

      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
    </ol>

    <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
    <var title="">children</var>.

    <li>Abort these steps.
  </ol>

  <li>If <var title="">current ancestor</var> is not an <a href=#editable>editable</a>
  <a href=#indentation-element>indentation element</a>, abort these steps.

  <li>
  <p class=comments>If we get to this point, we have an ancestor to split up.

  <p>Append <var title="">current ancestor</var> to <var title="">ancestor list</var>.

  <li>
  <p class=comments>We can't outdent it yet, because we need its children to
  remain intact for the loop.

  <p>Let <var title="">original ancestor</var> be <var title="">current ancestor</var>.

  <li>While <var title="">ancestor list</var> is not empty:

  <ol>
    <li>Let <var title="">current ancestor</var> be the last member of <var title="">ancestor
    list</var>.

    <li>Remove the last member from <var title="">ancestor list</var>.

    <li>Let <var title="">target</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">current ancestor</var>
    that is equal to either <var title="">node</var> or the last member of <var title="">ancestor
    list</var>.

    <li>If <var title="">target</var> is an <a href=#inline-node>inline node</a> that is not a
    <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, and its <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, remove <var title="">target</var>'s
    <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Let <var title="">preceding siblings</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-preceding title=concept-tree-preceding>precedings</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-sibling title=concept-tree-sibling>siblings</a> of
    <var title="">target</var>, and let <var title="">following siblings</var> be the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-following title=concept-tree-following>followings</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-sibling title=concept-tree-sibling>siblings</a> of <var title="">target</var>.

    <li><a href=#indent>Indent</a> <var title="">preceding siblings</var>.

    <li><a href=#indent>Indent</a> <var title="">following siblings</var>.
  </ol>

  <li><a href=#outdent>Outdent</a> <var title="">original ancestor</var>.
</ol>


<h3 id=toggling-lists>Toggling lists</h3>

<div class=note>
<p>This is the action for <a href=#the-insertorderedlist-command>the <code title="">insertOrderedList</code>
command</a> and <a href=#the-insertunorderedlist-command>the <code title="">insertUnorderedList</code>
command</a>, which behave identically except for which list type they
target.  It does several things that vary contextually.

<p>If everything in the selection is contained in the target list type already,
this more or less just outdents everything one step.  This is relatively
simple.

<p>Otherwise, it's slightly more complicated:

<p>First, any lists of the opposite list type (<var title="">other tag name</var>) get
converted to the target list type (<var title="">tag name</var>).  They get merged into
a sibling if appropriate, otherwise we <a href=#set-the-tag-name>set the tag name</a>.

<p>Then we go through all the affected nodes, handling each run of consecutive
siblings separately.  Any line that's not already wrapped in an <code title="">&lt;li&gt;</code> gets wrapped.  If the parent at this point isn't a list at
all, the run gets wrapped in a list.  If it's the wrong type of list, we
<a href=#split-the-parent>split the parent</a> and rewrap it in the right type of list.  That's
basically it, except that we have to exercise the usual care to try merging
with siblings and so forth.
</div>

<div class=comments>
<p>Research for insertOrderedList/insertUnorderedList: tested the following
command sequences in IE9, Firefox 4.0, Chrome 12 dev, Opera 11.10,
OpenOffice.org 3.2.1 Ubuntu package, Microsoft Office Word 2007.  The commands
"ol", "ul", "indent", "outdent" correspond in browsers to "insertOrderedList",
"insertUnorderedList", "indent", and "outdent"; in OO.org to "Numbering
On/Off", "Bullets On/Off", "Increase Indent", "Decrease Indent"; and in Word to
"Numbering", "Bullets", "Increase Indent", "Decrease Indent".

<p>Note: OO has a bunch of extra options, like "Promote One Level", "Demote One
Level", "Promote One Level With Subpoints", "Demote One Level With Subpoints",
"Insert Unnumbered Entry", "Restart Numbering".  The regular "Increase/Decrease
Indent" commands work oddly, and I assume they're not really meant to be used
inside lists.  Thus I also tested with "Promote One Level" and "Demote One
Level".  These are denoted by OO' instead of OO.

<p>Assume that there are style rules in effect like

<pre>ol ol { list-style-type: lower-alpha }
ol ol ol { list-style-type: lower-roman }</pre>

<p>This is the default appearance in Word, and I set OO to something similar
with Bullets and Numbering &srarr; Outline in the list editing toolbox.  I'm
ignoring bullet style throughout, for no particular reason.

<ul>
  <li>In an existing ordered list equivalent to &lt;ol&gt;&lt;li&gt;foo&lt;li&gt;bar&lt;li&gt;baz&lt;/ol&gt;quz:

  <ul>
    <li>Select "bar", do "ol":
    <dl>
      <dt>Word/OO <dd>Remove indent and number "2", change "3" to "2".
      <dt>Browsers <dd>Remove indent and number "2", change "3" to "1".
      <dt>Spec <dd>Same as browsers.
    </dl>

    <li>Select "bar", do "ul":
    <dl>
      <dt>Word <dd>Leave indent the same, change "2" to a bullet, change "3" to "2".
      <dt>OO <dd>Increase indent, change "2" to a bullet, change "3" to "2".
      <dt>IE <dd>Change all numbers to bullets.
      <dt>Firefox/Chrome/Opera <dd>Leave indent the same, change "2" to a bullet, change "3" to "1".
      <dt>Spec <dd>Same as Firefox/Chrome/Opera.
    </dl>

    <li>Select "bar", do "indent":
    <dl>
      <dt>Word/OO'/Browsers <dd>Increase indent, change "2" to "a", change "3" to "2".
      <dt>OO <dd>Increase indent, do not change any numbers.
      <dt>Spec <dd>Same as Word/OO'/Browsers.
    </dl>

    <li>Select "bar", do "outdent":
    <dl>
      <dt>Word <dd>Do nothing.
      <dt>OO <dd>Leave indent the same, de-indent "2" so it goes past the left margin (?!), do not change any numbers.
      <dt>OO' <dd>Option grayed out.
      <dt>Browsers <dd>Remove indent and the number "2", change "3" to "1".
      <dt>Spec <dd>Same as browsers.
    </dl>

    <li>Select "quz", do "ol":
    <dl>
      <dt>Word/OO/IE/Chrome <dd>Add as fourth item to existing list, numbered "4".
      <dt>Firefox/Opera <dd>Create new list, number the item "1".
      <dt>Spec <dd>Same as OO/Word/IE/Chrome.
    </dl>
  </ul>

  <li>In an existing ordered list equivalent to &lt;ol&gt;&lt;li&gt;foo&lt;br&gt;bar&lt;li&gt;baz&lt;/ol&gt;:
  <ul>
    <li>Select "foo", do "ol":
    <dl>
      <dt>Word/OO/IE/Chrome/Opera <dd>Remove indent from both "foo" and "bar", change "2" -&gt; "1".
      <dt>Firefox <dd>Increase indent for "foo" only, add additional "a" marker after "1" and before "foo".
      <dt>Spec <dd>Same as Word/OO/IE/Chrome/Opera.
    </dl>

    <li>Select "foo", do "ul":
    <dl>
      <dt>Word/Opera <dd>Change "1" -&gt; bullet, "2" -&gt; "1".
      <dt>OO <dd>Increase indent for both "foo" and "bar", change "1" -&gt; bullet, "2" -&gt; "1".
      <dt>IE <dd>Change all numbers to bullets.
      <dt>Firefox <dd>Increase indent for "foo" only, add additional bullet marker after "1" and before "foo".
      <dt>Chrome <dd>Remove indent from "bar", change "1" -&gt; bullet, "2" -&gt; "1".
      <dt>Spec <dd>Same as Word/Opera.
    </dl>

    <li>Select "foo", do "indent":
    <dl>
      <dt>Word <dd>Increase indent for whole list.
      <dt>OO <dd>Increase indent for both "foo" and "bar".
      <dt>OO' <dd>Increase indent for "foo", change "1" -&gt; "a".
      <dt>IE/Firefox non-CSS/Opera <dd>Increase indent for both "foo" and "bar", change "1" -&gt; "a", "2" -&gt; "1".
      <dt>Firefox CSS <dd>Increase indent for "foo" only (&lt;div style="margin-left: 40px"&gt;).
      <dt>Chrome <dd>Increase indent for "foo" only, add "a" before "foo", move "1" to be before "bar".
      <dt>Spec <dd>Same as IE/Firefox non-CSS/Opera.
    </dl>

    <li>Select "foo", do "outdent":
    <dl>
      <dt>Word <dd>Decrease indent for whole list, so it goes past the left margin.
      <dt>OO <dd>Decrease indent for "bar" and "1." (so "1." goes past the left margin), but not "foo".
      <dt>OO' <dd>Option grayed out.
      <dt>IE/Chrome/Opera <dd>Remove indent from both "foo" and "bar", remove "1", change "2" -&gt; "1".
      <dt>Firefox <dd>Do nothing.
      <dt>Spec <dd>Same as IE/Chrome/Opera.
    </dl>

    <li>Select "bar", do "ol":
    <dl>
      <dt>Word/OO/IE/Chrome/Opera <dd>Remove indent from both "foo" and "bar", change "2" -&gt; "1".
      <dt>Firefox <dd>Increase indent for "bar" only, add "a" marker before it.
      <dt>Spec <dd>Same as Word/OO/IE/Chrome/Opera.
    </dl>

    <li>Select "bar", do "ul":
    <dl>
      <dt>Word/Opera <dd>Change "1" -&gt; bullet, "2" -&gt; "1".
      <dt>OO <dd>Increase indent for both "foo" and "bar", change "1" -&gt; bullet, "2" -&gt; "1".
      <dt>IE <dd>Change all numbers to bullets.
      <dt>Firefox <dd>Increase indent for "bar" only, add bullet marker before it.
      <dt>Chrome <dd>Remove indent from "foo", change "1" -&gt; bullet and move it before "bar", change "2" -&gt; "1".
      <dt>Spec <dd>Same as Word/Opera.
    </dl>

    <li>Select "bar", do "indent":
    <dl>
      <dt>Word <dd>Increase indent for whole list.
      <dt>OO <dd>Increase indent for both "foo" and "bar".
      <dt>OO' <dd>Increase indent for "foo", change "1" -&gt; "a".
      <dt>IE/Firefox non-CSS/Opera <dd>Increase indent for both "foo" and "bar", change "1" -&gt; "a", "2" -&gt; "1".
      <dt>Firefox CSS <dd>Increase indent for "bar" only (&lt;div style="margin-left: 40px"&gt;).
      <dt>Chrome <dd>Increase indent for "bar" only, add "a" before "bar", move "bar" above "foo" (?!).
      <dt>Spec <dd>Same as IE/Firefox non-CSS/Opera.
    </dl>

    <li>Select "bar", do "outdent":
    <dl>
      <dt>Word <dd>Decrease indent for whole list, so it goes past the left margin.
      <dt>OO <dd>Decrease indent for "bar" and "1." (so "1." goes past the left margin), but not "foo".
      <dt>OO' <dd>Option grayed out.
      <dt>IE/Chrome/Opera <dd>Remove indent from both "foo" and "bar", remove "1", change "2" -&gt; "1".
      <dt>Firefox <dd>Do nothing.
      <dt>Spec <dd>Same as IE/Chrome/Opera.
    </dl>
  </ul>

  <li>In an existing nested ordered list equivalent to &lt;ol&gt;&lt;li&gt;foo&lt;ol&gt;&lt;li&gt;bar&lt;li&gt;baz&lt;/ol&gt;&lt;li&gt;quz&lt;/ol&gt;:
  <ul>
    <li>Select "bar", do "ol":
    <dl>
      <dt>Word/IE/Firefox <dd>Decrease indent, remove "a" ("bar" is aligned with "foo" with no marker of its own), change "b" -&gt; "a".
      <dt>OO <dd>Remove all indent, change "b" -&gt; "a".
      <dt>Chrome <dd>Decrease indent, change "a" -&gt; "2", "b" -&gt; "a", "2" -&gt; "3".
      <dt>Opera <dd>Decrease indent, change "a" -&gt; "2", "b" -&gt; "a", "2" -&gt; "4", insert extra "3" list marker before new "a".
      <dt>Spec <dd>Same as Chrome.
    </dl>

    <li>Select "bar", do "ul":
    <dl>
      <dt>Word/Firefox/Chrome <dd>Change "a" -&gt; bullet, "b" -&gt; "a".
      <dt>OO <dd>Increase indent, change "a" -&gt; bullet, "b" -&gt; "a".
      <dt>IE <dd>Change "a" and "b" to bullets.
      <dt>Opera <dd>Change "a" -&gt; bullet, "b" -&gt; "a", "2" -&gt; "4", insert extra list markers "2" and "3" before new bullet and "a".
      <dt>Spec <dd>Same as Word/Firefox/Chrome.
    </dl>

    <li>Select "bar", do "indent":
    <dl>
      <dt>Word/OO'/IE <dd>Increase indent, change "a" -&gt; "i", leave "b" alone.
      <dt>OO <dd>Increase indent, do not change numbers.
      <dt>Firefox/Chrome/Opera <dd>Increase indent, change "a" -&gt; "i", "b" -&gt; "a".
      <dt>Spec <dd>Same as Firefox/Chrome/Opera.
    </dl>

    <li>Select "bar", do "outdent":
    <dl>
      <dt>Word/OO'/IE/Chrome <dd>Decrease indent, change "a" -&gt; "2", "b" -&gt; "a", "2" -&gt; "3".
      <dt>OO <dd>Leave indent the same, de-indent "a" so it goes past the left margin (?!).
      <dt>Firefox <dd>Decrease indent, remove "a" ("bar" is aligned with "foo" with no marker of its own), change "b" -&gt; "a".
      <dt>Opera <dd>Decrease indent, change "a" -&gt; "2", "b" -&gt; "a", "2" -&gt; "4", insert extra list marker "3" before new "a".
      <dt>Spec <dd>Same as Word/OO'/IE/Chrome.
    </dl>
  </ul>

  <li>In existing nested lists equivalent to &lt;ol&gt;&lt;li&gt;foo&lt;ul&gt;&lt;li&gt;bar&lt;li&gt;baz&lt;/ul&gt;&lt;li&gt;quz&lt;/ol&gt;:
  <ul>
    <li>Select "bar", do "ol":
    <dl>
      <dt>Word <dd>Change all bullets to numbers.  (Not letters, even though indented!)
      <dt>OO <dd>Decrease indent, change first bullet -&gt; "2", "2" -&gt; "3".
      <dt>IE <dd>Change all bullets to letters.
      <dt>Firefox/Chrome <dd>Change first bullet to "a".
      <dt>Opera <dd>Change first bullet -&gt; "a", "2" -&gt; "4", insert extra list markers "2" and "3" before new "a" and bullet.
      <dt>Spec <dd>Same as Firefox/Chrome.
    </dl>

    <li>Select "bar", do "ul":
    <dl>
      <dt>Word/IE/Firefox <dd>Decrease indent, remove first bullet ("bar" is aligned with "foo" with no marker of its own).
      <dt>OO <dd>Remove all indent, remove first bullet, leave all else the same.
      <dt>Chrome <dd>Decrease indent, change first bullet -&gt; "2", "2" -&gt; "3".
      <dt>Opera <dd>Decrease indent, change first bullet -&gt; "2", "2" -&gt; "4", insert extra list marker "3" before old bullet.
      <dt>Spec <dd>Same as Chrome.
    </dl>

    <li>Select "bar", do "indent":
    <dl>
      <dt>Word <dd>Increase indent, change first bullet to "i" (?!).
      <dt>OO/OO'/Firefox/Chrome/Opera <dd>Increase indent.
      <dt>IE <dd>Increase indent, change "2" -&gt; "3" (?!?!).  (I don't see from the markup why the 2 actually changes to a 3.  The markup seems to be as other browsers.)
      <dt>Spec <dd>Same as OO/OO'/Firefox/Chrome/Opera.
    </dl>

    <li>Select "bar", do "outdent":
    <dl>
      <dt>Word/IE/Chrome <dd>Decrease indent, change first bullet -&gt; "2", "2" -&gt; "3".
      <dt>OO <dd>Usual crazy stuff, move bullet left but leave text alone.
      <dt>OO' <dd>Option grayed out.  (Interesting.)
      <dt>Firefox <dd>Decrease indent, remove first bullet ("bar" is aligned with "foo" with no marker of its own).
      <dt>Opera <dd>Decrease indent, change first bullet -&gt; "2", "2" -&gt; "4", insert extra list marker "3" before old bullet.
      <dt>Spec <dd>Same as Word/IE/Chrome.
    </dl>
  </ul>

  <li>In an existing nested ordered list equivalent to &lt;ol&gt;&lt;li&gt;foo&lt;li&gt;bar&lt;ol&gt;&lt;li&gt;baz&lt;/ol&gt;&lt;li&gt;quz&lt;/ol&gt;:
  <ul>
    <li>Select "bar", do "ol":
    <dl>
      <dt>Word/OO <dd>Remove indent and "2", change "3" -&gt; "2".
      <dt>IE/Chrome/Opera <dd>Remove indent and "2", decrease indent of "baz", change "2" and "3" -&gt; "1".
      <dt>Firefox <dd>Increase indent, add extra "a" marker between "2" and "bar".
      <dt>Spec <dd>Different from all of them: remove indent and "2", change "3" -&gt; "1".
    </dl>

    <li>Select "bar", do "ul":
    <dl>
      <dt>Word <dd>Change "2" -&gt; bullet.
      <dt>OO <dd>Increase indent, change "2" -&gt; bullet, "3" -&gt; "2".
      <dt>IE <dd>Change "1", "2", "3" -&gt; bullets (and "a" to "1").
      <dt>Firefox <dd>Increase indent, add extra bullet marker between "2" and "bar".
      <dt>Chrome <dd>Decrease indent of "baz", change "2" -&gt; bullet, "a" and "3" -&gt; "1".
      <dt>Opera <dd>Change "2" -&gt; bullet, "a" and "3" -&gt; "1".
      <dt>Spec <dd>Different from all of them: change "2" -&gt; bullet, "3" -&gt; "1".
    </dl>

    <li>Select "bar", do "indent":
    <dl>
      <dt>Word/OO' <dd>Increase indent, change "2" -&gt; "a", "a" -&gt; "b", "3" -&gt; "2".
      <dt>OO <dd>Increase indent (double amount, past "baz").
      <dt>Firefox non-CSS/Opera <dd>Increase indent of both "bar" and "baz", change "2" -&gt; "a", "a" -&gt; "i", "3" -&gt; "2".
      <dt>Firefox CSS <dd>Increase indent.
      <dt>Chrome <dd>Increase indent, add "a" marker before "bar", move "2" marker to before the "a" marker of "baz".
      <dt>Spec <dd>Same as Word/OO'.
    </dl>

    <li>Select "bar", do "outdent":
    <dl>
      <dt>Word/Firefox <dd>Do nothing.
      <dt>OO <dd>Decrease indent on "2", leave "bar" alone.
      <dt>OO' <dd>Option grayed out.
      <dt>IE <dd>Decrease indent of "baz", change "2" and "3" -&gt; "1", "a" -&gt; "2".
      <dt>Chrome/Opera <dd>Decrease indent of "bar" and "baz", remove "2", change "a" and "3" -&gt; "1".
      <dt>Spec <dd>Different from all of them: remove indent and "2", change "3" -&gt; "1".
    </dl>
  </ul>

  <li>In an existing nested ordered list equivalent to &lt;ol&gt;&lt;li&gt;foo&lt;li&gt;bar&lt;ol&gt;&lt;li&gt;baz&lt;/ol&gt;quz&lt;li&gt;qoz&lt;/ol&gt;:
  <ul>
    <li>Does not appear to be possible in Word or OO.
    <li>Also might be impossible to actually make such a list using execCommand() in browsers.
    <li>Suffice it to say that there's a lot of variation.
  </ul>

  <li>In an existing indented region equivalent to foo&lt;blockquote&gt;bar&lt;/blockquote&gt;baz:
  <ul>
    <li>Select "bar", do "ol":
    <dl>
      <dt>Word/OO/Firefox/Chrome <dd>Increase indent, add "1".
      <dt>IE <dd>Increase indent, add "a".
      <dt>Opera <dd>Add "1" (but do not increase indent).
    </dl>

    <li>Select "foobar", do "ol":
    <dl>
      <dt>Word/IE <dd>Increase indent of both, add "1" before "foo" and "a" before
      "bar".
      <dt>OO <dd>Increase indent of "bar" one step, increase indent of "foo" two steps
      so it's aligned with "bar", add "1" before "foo" and "2" before "bar".
      <dt>Firefox <dd>Increase indent of both, add "1" before foo", add "2" before
      "bar" aligned with the "1" of "foo" (so large gap between "2" and "bar").
      <dt>Chrome <dd>Increase indent of "foo", add "1" before "foo" and "2" before
      "bar".
      <dt>Opera <dd>Mash everything together on one line.  But if you do
      &lt;p&gt;foo&lt;/p&gt;&lt;blockquote&gt;bar&lt;/blockquote&gt;&lt;p&gt;baz&lt;/p&gt; instead, same as Chrome.
    </dl>

    <li>Select "foo" and do "ol", then select "bar" and do "ol":
    <dl>
      <dt>Word/OO/Firefox/Opera <dd>Different than doing both at once (often in
      exciting ways).
      <dt>IE/Chrome <dd>Same as doing both at once.
    </dl>
  </ul>

  <li>&lt;p&gt;foo&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;bar&lt;/p&gt;&lt;p&gt;baz&lt;/p&gt;&lt;/blockquote&gt;
  <ul>
    <li>Select "foobar" and do "ol":
    <dl>
      <dt>Word <dd>One-item list with sublist.
      <dt>OO/Firefox/Chrome/Opera <dd>One two-item list, unindented.
      <dt>IE9 <dd>Two one-item lists.
    </dl>

    <li>Select "foo", do "ol", then select "bar" and do "ol":
    <dl>
      <dt>Word/OO/Chrome <dd>One two-item list, unindented.
      <dt>IE9/Firefox <dd>Two one-item lists.
      <dt>Opera <dd>Two one-item lists, both unindented.
    </dl>

    <li>Desired behavior: One-item list with sublist in both cases.
  </ul>

  <li>In an existing multi-line indented region equivalent to &lt;blockquote&gt;foo&lt;br&gt;bar&lt;br&gt;baz&lt;/blockquote&gt;:
  <ul>
    <li>Select "bar", do "ol":
    <dl>
      <dt>Word/OO/Firefox/Chrome <dd>Increase indent, add "1".
      <dt>IE <dd>Increase indent of everything, add "a" before "foo".  If you do
      &lt;blockquote&gt;&lt;p&gt;foo&lt;p&gt;bar&lt;p&gt;baz&lt;/blockquote&gt;, same as
      Word/OO/Firefox/Chrome.
      <dt>Opera <dd>Don't increase indent of anything, add "1" before "bar".
    </dl>
  </ul>

  <li>In an existing multi-line indented region equivalent to &lt;blockquote&gt;foo&lt;br&gt;bar&lt;/blockquote&gt;baz:
  <ul>
    <li>Select "barbaz", do "ol":
    <dl>
      <dt>Word <dd>Indent both, add "a" before "bar" and "2" before "baz".
      <dt>OO <dd>Indent "baz", add "1" before "bar" and "2" before "baz".
      <dt>IE <dd>Indent everything, add "a" before "foo" and "1" before "baz".  If you
      do &lt;blockquote&gt;&lt;p&gt;foo&lt;p&gt;bar&lt;/blockquote&gt;&lt;p&gt;baz, indent "bar" and "baz"
      and put "1" before each.
      <dt>Firefox <dd>Indent "bar" and put "1" before it, put "baz" after "bar" on the
      same line.  If you do &lt;blockquote&gt;&lt;p&gt;foo&lt;p&gt;bar&lt;/blockquote&gt;&lt;p&gt;baz, same
      as Chrome.
      <dt>Chrome <dd>Indent "bar" once and "baz" twice, put "1" before "bar" and "2"
      before "baz".
      <dt>Opera <dd>Put a "1" before "bar" and move "baz" to the same line.  If you do
      &lt;blockquote&gt;&lt;p&gt;foo&lt;p&gt;bar&lt;/blockquote&gt;&lt;p&gt;baz, indent "baz", put a "1"
      before "bar" and a "2" before "baz".
    </dl>

    <li>Select "bar", do "ol", then select "baz" and do "ol":
    <dl>
      <dt>Word/OO/Opera <dd>Different from if you do both together.
      <dt>IE <dd>Different with &lt;br&gt;, same with &lt;p&gt;.
      <dt>Firefox <dd>Three behaviors, depending on whether you do it in one step with
      &lt;br&gt;, one step with &lt;p&gt;, or two steps with either (same behavior
      regardless with two steps).
      <dt>Chrome <dd>Same behavior in all four cases.
    </dl>
  </ul>

  <li>&lt;blockquote&gt;foo&lt;ol&gt;&lt;li&gt;bar&lt;/ol&gt;&lt;/blockquote&gt;baz:
  <ul>
    <li>Select "baz", do "ol":
    <dl>
      <dt>Word/OO/Chrome <dd>Add "baz" as a new item to existing list.
      <dt>IE/Firefox/Opera <dd>Make "baz" its own new list.
    </dl>
  </ul>

  <li>&lt;ul&gt;&lt;li&gt;foo&lt;/li&gt;&lt;ol&gt;&lt;li&gt;bar&lt;/li&gt;&lt;/ol&gt;&lt;/ul&gt;baz:
  <ul>
    <li>Select "baz", do "ol":
    <dl>
      <dt>IE/Firefox/Chrome/Opera <dd>Separate list.
    </dl>
  </ul>
</ul>

<p>Ignoring the conceptual model of HTML, which users won't understand, here's
the conceptual model I've developed for lists: text is divided up into blocks.
Each block has an indentation level and a list marker type.  The list marker
type can be either nothing, ordered, or unordered.  A list block cannot have
indentation level less than one.  Any given piece of text is part of only one
block.  A block may be visually non-contiguous, such as if a single list block
is interrupted by a further-indented block.

<p>To find the right number (or letter) for an ordered-list block, look at the
immediately preceding block, but skip over any blocks of higher indentation
level.  If there is no immediately preceding block, or it's not an ordered-list
block, or it has a lower indentation level, the number is 1 (or a, i, etc.).
Otherwise, it's the number of the preceding block plus one.

<p>ol/ul commands change the selected block to that list marker type, or remove
the list marker type if it's already the chosen type.  If the block has
indentation level zero, it increases to one.

<p>indent/outdent commands change the selected block's indentation level.  If a
list block's indentation level is reduced to zero, it's converted to a regular
block.

<p>What this means from an HTML perspective, roughly:

<ul>
  <li>A list block is the entire contents of an &lt;li&gt; element, ignoring any nested
  list elements or indentation elements.  A non-list block is a line box.

  <li>Indentation level is equal to the number of ancestor elements that are either
  &lt;li&gt;s or indentation elements (blockquotes or indenting divs).

  <li>To find the list marker type, go to the first ancestor that's either an &lt;li&gt;
  or indentation element.

  <li>Correct numbering should automatically follow from the way &lt;ol&gt; works in HTML
  (which is one of the reasons I use this model).

  <li>An ol command in an ordered-list block removes the surrounding &lt;li&gt;,
  migrating its contents into the parent of the &lt;ol&gt;.  This splits up the &lt;ol&gt; if
  it's not the first or last child, and wraps the contents in a new &lt;li&gt; if
  necessary.  If there's another list or indentation element nested in the &lt;li&gt;
  we're removing, it will get re-wrapped in a new &lt;ol&gt;, outside the
  newly-created &lt;li&gt;, so that it maintains its indentation.  This might cause
  the new &lt;li&gt; to wind up in multiple pieces, if the original block was not
  contiguous, which means the non-contiguous block is split into several blocks
  (with different numbers).

  <li>An ol command in an unordered-list block breaks up the parent &lt;ul&gt; and puts a
  new &lt;ol&gt; in between the two pieces, moving the parent &lt;li&gt; into it.  If the
  &lt;li&gt; was the first or last child, we merge with an existing adjacent &lt;ol&gt; if
  possible.  All children stay as they are.

  <li>An ol command in a non-list block with indentation zero wraps it in a new
  &lt;ol&gt;&lt;li&gt;, or merges with an adjacent &lt;ol&gt; if possible.

  <li>An ol command in a non-list block with nonzero indentation converts the
  parent to an &lt;ol&gt;&lt;li&gt;, breaking it up if necessary.

  <li>The ul command works similarly to ol.

  <li>indent in a non-list block wraps in an indentation element.  In a list block,
  it wraps the &lt;li&gt; in an extra &lt;ol&gt; or &lt;ul&gt; as appropriate.  With merging.
  Whatever.  Let me just write the spec.

  <li>outdent in a non-list block strips an indentation element, if one is present.
  In a list block, it breaks apart the parent &lt;ol&gt; or &lt;ul&gt; and makes the
  affected block a sibling in between the newly-split list elements.  Will
  create new &lt;li&gt;s, etc. etc.
</ul>

<p>Sheesh, lists are complicated.
</div>

<p>To <dfn id=toggle-lists>toggle lists</dfn>, given a string <var title="">tag name</var> (either "ol"
or "ul"):

<ol>
  <li>Let <var title="">mode</var> be "disable" if the <a href="#selection's-list-state">selection's list
  state</a> is <var title="">tag name</var>, and "enable" otherwise.

  <li>Let <var title="">other tag name</var> be "ol" if <var title="">tag name</var> is "ul", and
  "ul" if <var title="">tag name</var> is "ol".

  <li>Let <var title="">items</var> be a list of all <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>s that are
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestors</a> of the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>
  and/or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>.

  <li>
  <p class=comments>TODO: This overnormalizes, but it seems like the simplest
  solution for now.

  <p>For each <var title="">item</var> in <var title="">items</var>, <a href=#normalize-sublists>normalize
  sublists</a> of <var title="">item</var>.

  <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>If <var title="">mode</var> is "enable", then let <var title="">lists to convert</var>
  consist of every <a href=#editable>editable</a> <a href=#html-element>HTML element</a> with
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">other tag name</var> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new
  range</var>, and for every <var title="">list</var> in <var title="">lists to convert</var>:

  <ol>
    <li>
    <p class=comments>Convert it to the right name.  If possible, we want to
    merge with a neighboring list of the correct type.  Failing that, we set
    the tag name.

    <p>If <var title="">list</var>'s <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> or <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is an
    <a href=#editable>editable</a> <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag
    name</var>:

    <ol>
      <li>Let <var title="">children</var> be <var title="">list</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>.

      <li><a href=#record-the-values>Record the values</a> of <var title="">children</var>, and let
      <var title="">values</var> be the result.

      <li><a href=#split-the-parent>Split the parent</a> of <var title="">children</var>.

      <li><a href=#wrap>Wrap</a> <var title="">children</var>, with <var title="">sibling
      criteria</var> returning true for an <a href=#html-element>HTML element</a> with
      <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var> and false otherwise.

      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
    </ol>

    <li>Otherwise, <a href=#set-the-tag-name>set the tag name</a> of <var title="">list</var> to <var title="">tag
    name</var>.
  </ol>

  <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

  <li>
  <div class=comments>
  <p>We exclude indentation elements so that selecting some random text and
  doing indent followed by insertOrderedList will have the same result as the
  reverse.  Specifically,

<pre>&lt;blockquote&gt;[foo]&lt;/blockquote&gt; -&gt;
&lt;blockquote&gt;&lt;ol&gt;&lt;li&gt;[foo]&lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;</pre>

  <p>per spec and Firefox 4.0 and (more or less) Chrome 12 dev.  Opera 11.10
  instead does &lt;ol&gt;&lt;li&gt;foo&lt;/li&gt;&lt;/ol&gt;, so the indentation vanishes.
  IE9 does &lt;ol&gt;&lt;ol&gt;&lt;li&gt;foo&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;, but that doesn't
  make semantic sense and is different from how it would work if you reversed
  the commands.  OpenOffice.org 3.2.1 (Ubuntu) and Word 2007 both agree with
  the spec in this case.
  </div>

  <p>For each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var>,
  if <var title="">node</var> is <a href=#editable>editable</a>; the last member of <var title="">node
  list</var> (if any) is not an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
  <var title="">node</var> is not an <a href=#indentation-element>indentation element</a>; and either
  <var title="">node</var> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, or its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or
  <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, or it is an <a href=#allowed-child>allowed child</a> of "li"; then append
  <var title="">node</var> to <var title="">node list</var>.

  <li>
  <div class=comments>
  <p>We don't want to touch these.  E.g., assuming tag name is "ol",

<pre>[foo&lt;ol&gt;&lt;li&gt;bar&lt;/ol&gt;baz]
-&gt; &lt;ol&gt;&lt;li&gt;[foo&lt;li&gt;bar&lt;li&gt;baz]&lt;/ol&gt;
not &lt;ol&gt;&lt;li&gt;[foo&lt;/li&gt;&lt;ol&gt;&lt;li&gt;bar&lt;/ol&gt;&lt;li&gt;baz]&lt;/ol&gt;.</pre>

  <p>But

<pre>&lt;ul&gt;&lt;li&gt;foo&lt;li&gt;[bar&lt;/li&gt;&lt;ol&gt;&lt;li&gt;baz&lt;/ol&gt;&lt;li&gt;quz]&lt;/ul&gt;
-&gt; &lt;ul&gt;&lt;li&gt;foo&lt;/ul&gt;&lt;ol&gt;&lt;li&gt;[bar&lt;/li&gt;&lt;ol&gt;&lt;li&gt;baz&lt;/ol&gt;&lt;li&gt;quz]&lt;/ol&gt;
not &lt;ul&gt;&lt;li&gt;foo&lt;/ul&gt;&lt;ol&gt;&lt;li&gt;[bar&lt;/ol&gt;&lt;ul&gt;&lt;ol&gt;&lt;li&gt;baz&lt;/ol&gt;&lt;/ul&gt;&lt;ol&gt;&lt;li&gt;quz]&lt;/ol&gt;</pre>
  </div>

  <p>If <var title="">mode</var> is "enable", remove from <var title="">node list</var> any
  <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not also an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>.

  <li>If <var title="">mode</var> is "disable", then while <var title="">node list</var> is not
  empty:

  <ol>
    <li>Let <var title="">sublist</var> be an empty list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>.

    <li>Remove the first member from <var title="">node list</var> and append it to
    <var title="">sublist</var>.

    <li>If the first member of <var title="">sublist</var> is an <a href=#html-element>HTML
    element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var>, <a href=#outdent>outdent</a>
    it and continue this loop from the beginning.

    <li>While <var title="">node list</var> is not empty, and the first member of
    <var title="">node list</var> is the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> of the last member of
    <var title="">sublist</var> and is not an <a href=#html-element>HTML element</a> with
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var>, remove the first member from <var title="">node
    list</var> and append it to <var title="">sublist</var>.

    <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
    <var title="">values</var> be the result.

    <li><a href=#split-the-parent>Split the parent</a> of <var title="">sublist</var>.

    <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
    <var title="">sublist</var>.

    <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
  </ol>

  <li>Otherwise, while <var title="">node list</var> is not empty:

  <ol>
    <li>Let <var title="">sublist</var> be an empty list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>.

    <li>
    <p class=comments>Accumulate consecutive sibling nodes in sublist, first
    converting them all to li's (except if they're already lists).

    <p>While either <var title="">sublist</var> is empty, or <var title="">node list</var> is
    not empty and its first member is the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> of
    <var title="">sublist</var>'s last member:

    <ol>
      <li>
      <p class=comments>Thus &lt;p&gt;foo&lt;/p&gt; becomes &lt;ol&gt;&lt;li&gt;foo&lt;/ol&gt;
      instead of &lt;ol&gt;&lt;li&gt;&lt;p&gt;foo&lt;/ol&gt;, and likewise for div, but
      other things will be put inside the &lt;li&gt;.

      <p>If <var title="">node list</var>'s first member is a <code class=external data-anolis-spec=html title="the p element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-p-element>p</a></code> or <code class=external data-anolis-spec=html title="the div element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-div-element>div</a></code>,
      <a href=#set-the-tag-name>set the tag name</a> of <var title="">node list</var>'s first member to
      "li", and append the result to <var title="">sublist</var>.  Remove the first
      member from <var title="">node list</var>.

      <li>Otherwise, if the first member of <var title="">node list</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>
      or <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, remove it from <var title="">node list</var> and append it to
      <var title="">sublist</var>.

      <li>Otherwise:

      <ol>
        <li>Let <var title="">nodes to wrap</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially
        empty.

        <li>While <var title="">nodes to wrap</var> is empty, or <var title="">node list</var> is
        not empty and its first member is the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> of
        <var title="">nodes to wrap</var>'s last member and the first member of
        <var title="">node list</var> is an <a href=#inline-node>inline node</a> and the last member
        of <var title="">nodes to wrap</var> is an <a href=#inline-node>inline node</a> other than a
        <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, remove the first member from <var title="">node list</var> and append it
        to <var title="">nodes to wrap</var>.

        <li><a href=#wrap>Wrap</a> <var title="">nodes to wrap</var>, with <var title="">new parent
        instructions</var> returning the result of calling
        <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("li")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.  Append the result to
        <var title="">sublist</var>.
      </ol>
    </ol>

    <li>
    <p class=comments>In this case it's already wrapped properly, nothing more
    to do.

    <p>If <var title="">sublist</var>'s first member's <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <a href=#html-element>HTML
    element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var>, or if every member
    of <var title="">sublist</var> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, continue this loop from the
    beginning.

    <li>If <var title="">sublist</var>'s first member's <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <a href=#html-element>HTML
    element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">other tag name</var>:

    <ol>
      <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
      <var title="">values</var> be the result.

      <li><a href=#split-the-parent>Split the parent</a> of <var title="">sublist</var>.

      <li><a href=#wrap>Wrap</a> <var title="">sublist</var>, with <var title="">sibling
      criteria</var> returning true for an <a href=#html-element>HTML element</a> with
      <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var> and false otherwise, and <var title="">new
      parent instructions</var> returning the result of calling
      <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">tag name</var>)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.

      <li>Continue this loop from the beginning.
    </ol>

    <li><a href=#wrap>Wrap</a> <var title="">sublist</var>, with <var title="">sibling criteria</var>
    returning true for an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag
    name</var> and false otherwise, and <var title="">new parent instructions</var>
    being the following:

    <ol>
      <li>
      <div class=comments>
      <p>Special case: something like
        <pre>&lt;ol&gt;&lt;li&gt;foo&lt;/ol&gt;&lt;blockquote&gt;[bar]&lt;/blockquote&gt;</pre>
      <p>becomes
        <pre>&lt;ol&gt;&lt;li&gt;foo&lt;/li&gt;&lt;ol&gt;&lt;li&gt;[bar]&lt;/ol&gt;&lt;/ol&gt;</pre>
      <p>instead of
        <pre>&lt;ol&gt;&lt;li&gt;foo&lt;/ol&gt;&lt;blockquote&gt;&lt;ol&gt;&lt;li&gt;[bar]&lt;/ol&gt;&lt;/blockquote&gt;.</pre>
      <p>We handle the special case in <var title="">new parent instructions</var>
      instead of outside because we'd prefer to wind up in a sibling if there
      is one.  We handle only previousSibling, not nextSibling, because we
      really mean for this to cover something like
        <pre>[foo&lt;blockquote&gt;bar]&lt;/blockquote&gt;</pre>
      <p>which we'll handle node-by-node.  TODO: Maybe we should do this
      differently, like just special-case simple indentation elements in an
      earlier part of the algorithm?  This way's a bit weird.
      </div>

      <p>If <var title="">sublist</var>'s first member's <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not an
      <a href=#editable>editable</a> <a href=#simple-indentation-element>simple indentation element</a>, or
      <var title="">sublist</var>'s first member's <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>'s <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> is
      not an <a href=#editable>editable</a> <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a>
      <var title="">tag name</var>, call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">tag name</var>)</a></code> on the
      <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and return the result.

      <li>Let <var title="">list</var> be <var title="">sublist</var>'s first member's
      <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>'s <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code>.

      <li><a href=#normalize-sublists>Normalize sublists</a> of <var title="">list</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code>.

      <li>If <var title="">list</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> is not an <a href=#editable>editable</a>
      <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">tag name</var>, call
      <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">tag name</var>)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>, and
      append the result as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">list</var>.

      <li>Return the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">list</var>.
    </ol>

    <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of the previous step's result.
  </ol>
</ol>


<h3 id=justifying-the-selection>Justifying the selection</h3>

<p class=note>This is the <a href=#action>action</a> for the four <code title="">justify*</code> commands.  It's pretty straightforward, with no notable
gotchas or special cases.  It works more or less like a stripped-down version
of <a href="#set-the-selection's-value">set the selection's value</a>, except it gets to be much simpler
because it's much less general.  (It's not similar enough to just invoke that
algorithm: too many things differ between block and inline elements.)

<div class=comments>
<p>There are two basic ways this works in browsers: using the align attribute,
and using CSS text-align.  IE9 and Opera 11.11 use only the align attribute,
Chrome 13 dev uses only text-align, and Firefox 5.0a2 varies based on
styleWithCSS.  The two ways produce entirely different results, which is a real
problem, so I don't think Firefox's approach is tenable.  text-align is more
valid, and for typical contenteditable cases it works the same.  But for cases
where you have fixed-width blocks, like tables or just divs with a width set,
it behaves differently, and in those cases the align attribute is more useful.

<p>TODO: text-align doesn't behave as expected if there are descendant blocks
with non-100% width, like tables.  The align attribute behaves a lot more
nicely in such cases, but it's not valid.  Not clear what to do.  For now I've
stuck with text-align, just because the cases where it misbehaves can't be
created by any sequence of stock execCommand()s that I know of, but this needs
more careful consideration.  Gecko in CSS mode seems to special-case tables,
adding auto margins to the table element to get it to align correctly.

<p>TODO: We could do something along the lines of pushing down values here,
although no browser does.  In fact, it's very likely this can be rewritten in
terms of the inline formatting command primitives, but it's not clear if it
would be worth the added complexity.
</div>

<p>To <dfn id=justify-the-selection>justify the selection</dfn> to a string <var title="">alignment</var> (either
"center", "justify", "left", or "right"):

<ol>
  <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>
  <p class=comments>No browser actually removes center, but it makes sense to
  do so.

  <p>Let <var title="">element list</var> be a list of all <a href=#editable>editable</a>
  <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var> that either has an
  attribute in the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#html-namespace>HTML namespace</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-attribute-local-name title=concept-attribute-local-name>local name</a> is "align", or has
  a <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute that sets "text-align", or is a <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#center>center</a></code>.

  <li>For each <var title="">element</var> in <var title="">element list</var>:

  <ol>
    <li>If <var title="">element</var> has an attribute in the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#html-namespace>HTML namespace</a> whose
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-attribute-local-name title=concept-attribute-local-name>local name</a> is "align", remove that attribute.

    <li>Unset the CSS property "text-align" on <var title="">element</var>, if it's set
    by a <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute.

    <li>If <var title="">element</var> is a <code class=external data-anolis-spec=html title="the div element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-div-element>div</a></code> or <code class=external data-anolis-spec=html title="the span element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-span-element>span</a></code> or <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#center>center</a></code> with no attributes, remove it,
    <a href=#preserving-its-descendants>preserving its descendants</a>.

    <li>If <var title="">element</var> is a <code class=external data-anolis-spec=html><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#center>center</a></code>
    with one or more attributes, <a href=#set-the-tag-name>set the tag name</a> of
    <var title="">element</var> to "div".
  </ol>

  <li>
  <p class=comments>This could theoretically be necessary, like if it converted
  "&lt;div align=right&gt;foo&lt;/div&gt;bar" to "foo&lt;br&gt;bar".  Now we need to
  select "foo&lt;br&gt;", nor just "foo".

  <p><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

  <li>
  <p class=comments>Of tested browsers, only Chrome 13 dev seems to not apply
  the alignment to nodes that are already aligned.  Even then, it does apply it
  if the alignment is just inherited from the root.

  <p>For each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var>,
  append <var title="">node</var> to <var title="">node list</var> if the last member of
  <var title="">node list</var> (if any) is not an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
  <var title="">node</var> is <a href=#editable>editable</a>; <var title="">node</var> is an <a href=#allowed-child>allowed
  child</a> of "div"; and <var title="">node</var>'s <a href=#alignment-value>alignment value</a> is
  not <var title="">alignment</var>.

  <li>While <var title="">node list</var> is not empty:

  <ol>
    <li>Let <var title="">sublist</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

    <li>Remove the first member of <var title="">node list</var> and append it to
    <var title="">sublist</var>.

    <li>While <var title="">node list</var> is not empty, and the first member of
    <var title="">node list</var> is the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> of the last member of
    <var title="">sublist</var>, remove the first member of <var title="">node list</var> and
    append it to <var title="">sublist</var>.

    <li><p><a href=#wrap>Wrap</a> <var title="">sublist</var>.  <var title="">Sibling criteria</var>
    returns true for any <code class=external data-anolis-spec=html title="the div element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-div-element>div</a></code> that has one or both of the following two
    attributes and no other attributes, and false otherwise:

    <ul>
      <li>An <code class=external data-anolis-spec=html title=attr-div-align><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#attr-div-align>align</a></code>
      attribute whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-attribute-value title=concept-attribute-value>value</a> is an <a class=external data-anolis-spec=domcore href=http://dom.spec.whatwg.org/#ascii-case-insensitive>ASCII
      case-insensitive</a> match for <var title="">alignment</var>.

      <li>A <code class=external data-anolis-spec=html title="the style attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-style-attribute>style</a></code> attribute which sets exactly one CSS property (including
      unrecognized or invalid attributes), which is "text-align", which is set
      to <var title="">alignment</var>.
    </ul>

    <p class=comments>As with inline formatting, I only ever create new
    elements, and don't ever modify existing ones.  This doesn't match how any
    browser behaves in this case, but for inline formatting it matches everyone
    but Gecko's CSS mode, so I'm just being consistent.

    <p><var title="">New parent instructions</var> are to call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("div")</a></code>
    on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>, then set its CSS property "text-align" to
    <var title="">alignment</var> and return the result.
  </ol>
</ol>


<h3 id=automatic-linking>Automatic linking</h3>

<p class=comments><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13807">Bug 13807</a>.

<p class=note>When the user inserts whitespace immediately following something
that looks like a URL or e-mail address, we automatically run <a href=#the-createlink-command>the <code title="">createLink</code> command</a> on it.

<p>An <dfn id=autolinkable-url>autolinkable URL</dfn> is a string of the following form:

<ol>
  <li>
  <p class=comments>IE9 and LibreOffice 3.3.4 both have a whitelist of URL
  schemes.  That would be complicated and involve political decisions, so
  instead, we'll just accept anything that looks like a hierarchical URL
  scheme.  Google Docs is similar (as of November 9, 2011), but it's too lax,
  and allows characters in the scheme that can't be in a scheme.  For
  non-hierarchical schemes, we just whitelist mailto:, since it's the only
  common one that makes sense to autolink.

  <p>Either a string matching the <var title="">scheme</var> pattern from <a href=https://tools.ietf.org/html/rfc3986#section-3.1>RFC 3986 section 3.1</a>
  followed by the literal string <code title="">://</code>, or the literal string
  <code title="">mailto:</code>; followed by

  <li>
  <p class=comments>We don't try to enforce that the URL is anything resembling
  valid per spec.  Too complicated for not enough gain.

  <p>Zero or more characters other than <a class=external data-anolis-spec=encoding href=http://encoding.spec.whatwg.org/#ascii-whitespace title="ascii whitespace">space characters</a>; followed by

  <li>
  <div class=comments>
  <p>If the user types a URL followed by some punctuation, we still want to
  autolink, but we don't want to include the punctuation if it's probably not
  meant as part of the URL.

  <p>IE9 excludes <code title="">!#&amp;()*+,-.:;&lt;=?@[]^_`{|}~</code> as
  trailing characters from both URLs and e-mails.  A trailing <code title="">"</code> or
  <code title="">&gt;</code> will prevent autolinking, and a trailing <code title="">$%'/\</code> is
  included in the link.

  <p>LibreOffice 3.3.4 excludes trailing <code title="">!&rdquo;#'()*+,.:;&lt;=&gt;?[\]^_`{|}~</code>,
  and prevents autolinking on <code title="">$%&amp;-@</code>.  It includes a trailing
  <code title="">/</code> in URLs, but it inhibits linking for e-mails.

  <p>Google Docs (as of November 9, 2011) is complicated.  Trailing
  <code title="">&rdquo;&rsquor;,-.</code> always prevents autolinking of a URL, and trailing
  <code title="">#%/?_</code> is always included in a URL.  Trailing <code title="">!&amp;=$()*+:;&lt;&gt;@[\]^`{|}~</code> prevent autolinking if there's no
  <code title="">?</code> before them, but are included in the URL if there is a <code title="">?</code>.
  For e-mails, <code title="">_</code> is included, and everything else prevents
  autolinking.

  <p>None of these behaviors makes maximal sense.  We should exclude characters
  if they're more likely as delimiters than actual trailing characters; include
  them if they're more likely as actual trailing characters; and prevent
  autolinking if their presence suggests that we're not actually looking at a
  link or e-mail address.  The lists I made up for URLs are: exclude trailing
  <code title="">!"'(),-.:;&lt;&gt;[]`{}</code>, include anything else.  For e-mail,
  exclude anything at all.
  </div>

  <p>A character that is not one of the ASCII characters <code title="">!"'(),-.:;&lt;&gt;[]`{}</code>.
</ol>

<p>To <dfn id=autolink>autolink</dfn> (<var title="">node</var>, <var title="">end offset</var>):

<ol>
  <li>While (<var title="">node</var>, <var title="">end offset</var>)'s <a href=#previous-equivalent-point>previous
  equivalent point</a> is not null, set it to its <a href=#previous-equivalent-point>previous equivalent
  point</a>.

  <li>If <var title="">node</var> is not a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, or has an <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a>,
  do nothing and abort these steps.

  <li>Let <var title="">search</var> be the largest substring of <var title="">node</var>'s
  <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> whose end is <var title="">end offset</var> and that contains no
  <a class=external data-anolis-spec=encoding href=http://encoding.spec.whatwg.org/#ascii-whitespace title="ascii whitespace">space characters</a>.

  <li>If some substring of <var title="">search</var> is an <a href=#autolinkable-url>autolinkable
  URL</a>:

  <ol>
    <li>While there is no substring of <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> ending at
    <var title="">end offset</var> that is an <a href=#autolinkable-url>autolinkable URL</a>, decrement
    <var title="">end offset</var>.

    <li>Let <var title="">start offset</var> be the start index of the longest substring
    of <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> that is an <a href=#autolinkable-url>autolinkable URL</a>
    ending at <var title="">end offset</var>.

    <li>Let <var title="">href</var> be the substring of <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code>
    starting at <var title="">start offset</var> and ending at <var title="">end offset</var>.
  </ol>

  <li>Otherwise, if some substring of <var title="">search</var> is a <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address>valid e-mail address</a>:

  <ol>
    <li>While there is no substring of <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> ending at
    <var title="">end offset</var> that is a <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address>valid e-mail
    address</a>, decrement <var title="">end offset</var>.

    <li>Let <var title="">start offset</var> be the start index of the longest substring
    of <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> that is a <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address>valid
    e-mail address</a> ending at <var title="">end offset</var>.

    <li>Let <var title="">href</var> be "mailto:" concatenated with the substring of
    <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> starting at <var title="">start offset</var> and ending
    at <var title="">end offset</var>.
  </ol>

  <li>Otherwise, do nothing and abort these steps.

  <li>Let <var title="">original range</var> be the <a href=#active-range>active range</a>.

  <li>Create a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> (<var title="">node</var>, <var title="">start
  offset</var>) and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> (<var title="">node</var>, <var title="">end offset</var>), and
  set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to it.

  <li>Take the <a href=#action>action</a> for "createLink", with <var title="">value</var>
  equal to <var title="">href</var>.

  <li>Set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> to <var title="">original
  range</var>.
</ol>


<h3 id=the-delete-command><dfn>The <code title="">delete</code> command</dfn></h3>

<div class=note>
<p>This is the same as hitting backspace (see <a href=#additional-requirements>Additional requirements</a>).  The easy part is
if the selection isn't collapsed: just <a href=#delete-the-selection>delete the selection</a>.  But
it turns out rich-text editors have a lot of special behaviors for hitting
backspace with a collapsed selection.  Most obviously, if there's a text node
right before the cursor (maybe wrapped in some inline elements), we delete its
last character.  But some of the special cases we run into are:

<ul>
  <li><a href=#invisible>Invisible</a> nodes are removed before anything else happens.

  <li>An <code title="">&lt;a&gt;</code> gets removed if you backspace while the cursor is right
  after it, so the link disappears.

  <li>A <code title="">&lt;br&gt;</code> or <code title="">&lt;hr&gt;</code> or <code title="">&lt;img&gt;</code> gets deleted.

  <li>Backspacing at the start of most blocks merges with the previous block.
  (Visually, this is a matter of deleting a line break.)

  <li>Backspacing at the start of an <a href=#indentation-element>indentation element</a>, or an
  <code title="">&lt;li&gt;</code> or <code title="">&lt;dt&gt;</code> or <code title="">&lt;dd&gt;</code> that's at the beginning of a
  list, outdents the current block (rather than merging with the previous
  block).

  <li>Backspacing at the start of a table cell does nothing.

  <li>Backspacing immediately after a table selects the table, so a second
  backspace deletes it.

  <li>Backspacing at the start of a list item that's not at the beginning of a
  list merges with the previous list item, but keeps the contents on a separate
  line, so you have to hit backspace a second time to get them on the same
  line.
</ul>
</div>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p class=comments>For all the deletions here, Firefox 7.0a2 will remove wrapper
elements like &lt;b&gt; only if they're selected, like {&lt;b&gt;foo&lt;/b&gt;}.  IE9,
Chrome 14 dev, and Opera 11.50 will all remove them even if only their contents
are selected, like &lt;b&gt;[foo]&lt;/b&gt;.  Gecko's behavior in the latter case
leaves things like &lt;b&gt;{}&lt;/b&gt; in the DOM, which is unhelpful, so I don't.

<p><a href=#action>Action</a>:

<ol>
  <li>If the <a href=#active-range>active range</a> is not <code class=external data-anolis-spec=dom title=dom-Range-collapsed><a href=http://dom.spec.whatwg.org/#dom-range-collapsed>collapsed</a></code>, <a href=#delete-the-selection>delete
  the selection</a> and return true.

  <li>
  <p class=comments>Needed so that if there are multiple consecutive spaces we
  backspace over all at once.

  <p><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>.

  <li>Let <var title="">node</var> and <var title="">offset</var> be the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>.

  <li>
  <p class=comments>First go up as high as possible within the current block,
  then drill down to the lowest possible level, in the hopes that we'll wind up
  at the end of a text node, or maybe in a br or hr.

  <p>Repeat the following steps:

  <ol>
    <li>
    <p class=comments> If there's an invisible node somewhere, Firefox 5.0a2
    removes that node and then stops, so each backspace removes one invisible
    node.  All others remove the invisible node and then continue on looking
    for something visible to remove.  The spec follows the latter behavior,
    since it makes more sense to the user.  Of course, the definition of
    "invisible node" is not necessarily anything like the spec's.

    <p>If <var title="">offset</var> is zero and <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code>
    is an <a href=#editable>editable</a> <a href=#invisible>invisible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, remove
    <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, if <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var> &minus; 1 and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is an <a href=#editable>editable</a>
    <a href=#invisible>invisible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, remove that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> from
    <var title="">node</var>, then subtract one from <var title="">offset</var>.

    <li>Otherwise, if <var title="">offset</var> is zero and <var title="">node</var> is an
    <a href=#inline-node>inline node</a>, or if <var title="">node</var> is an
    <a href=#invisible>invisible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, set <var title="">offset</var> to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of
    <var title="">node</var>, then set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>
    <p class=comments> When backspacing a link, Firefox 7.0a2, Chrome 14 dev,
    Opera 11.50, and OpenOffice.org 3.2.1 Ubuntu have no special behavior.  IE9
    and Word 2007 remove the link instead of deleting its last character.  The
    latter behavior seems more useful and intuitive.

    <p>Otherwise, if <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var> &minus; 1 and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is an <a href=#editable>editable</a>
    <code class=external data-anolis-spec=html title="the a element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-a-element>a</a></code>, remove that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> from <var title="">node</var>, <a href=#preserving-its-descendants>preserving its
    descendants</a>.  Then return true.

    <li>Otherwise, if <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var> &minus; 1 and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is not a <a href=#block-node>block
    node</a> or a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> or an <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#the-img-element>img</a></code>, set <var title="">node</var> to that
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, then set <var title="">offset</var> to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of
    <var title="">node</var>.

    <li>Otherwise, break from this loop.
  </ol>

  <li>
  <div class=comments>
  <p>At this point, node cannot be an invisible node.  There are three cases:

  <ol>
    <li><var title="">offset</var> is zero and node is a block node.  Then we'll usually
    merge with the previous block if one exists.

    <li><var title="">offset</var> is not zero, <var title="">node</var> is not a block node, and
    <var title="">node</var> does not have a child with index <var title="">offset</var> &minus;
    1.  The only way this is possible is if node has a length greater than zero
    but no children, which implies it's a text or comment or PI.  Comments and
    PIs are invisible nodes, so it must be a text node.  We delete the previous
    character.

    <li><var title="">offset</var> is not zero, and the child of <var title="">node</var> with
    index <var title="">offset</var> &minus; 1 is a block node or a br or an img.  Then
    we'll usually merge the <var title="">offset</var>th child of <var title="">node</var> with
    the last descendant of the <var title="">offset</var> &minus; 1st.
  </ol>

  <p>Unlike forwardDelete, there's no special case for diacritics.  This means
  backspacing will just delete the last combining diacritic typed, or the whole
  character if it's precomposed.  This matches everything I tested (IE9,
  Firefox 7.0a2, Chrome 14 dev, etc.).
  </div>

  <p>If <var title="">node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and <var title="">offset</var> is not zero,
  or if <var title="">node</var> is a <a href=#block-node>block node</a> that has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">offset</var> &minus; 1 and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> or
  <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#the-img-element>img</a></code>:

  <ol>
    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">node</var>, <var title="">offset</var> &minus; 1)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li><a href=#delete-the-selection>Delete the selection</a>.

    <li>Return true.
  </ol>

  <li>
  <p class=comments>At the time of this writing, this should be impossible.
  Just being safe.

  <p>If <var title="">node</var> is an <a href=#inline-node>inline node</a>, return true.

  <li>
  <p class=comments> If we're at the beginning of a list, we want to outdent
  the first list item.  This doesn't actually match anyone or anything.  Word
  2007 and OpenOffice.org 3.2.1 Ubuntu just remove the list marker, which is
  weird and doesn't map well to HTML.  Browsers tend to just merge with the
  preceding block, which isn't expected.

  <p>If <var title="">node</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code> and is the first
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>, and <var title="">offset</var> is zero:

  <ol>
    <li>Let <var title="">items</var> be a list of all <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>s that are
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> of <var title="">node</var>.

    <li><a href=#normalize-sublists>Normalize sublists</a> of each <var title="">item</var> in
    <var title="">items</var>.

    <li><a href=#record-the-values>Record the values</a> of the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of
    <var title="">node</var>, and let <var title="">values</var> be the result.

    <li><a href=#split-the-parent>Split the parent</a> of the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of
    <var title="">node</var>.

    <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.

    <li>
    <p class=comments> Annoying hack to prevent the dl from being re-added when
    fixing disallowed ancestors.  In most cases we want a wrapper dl added, but
    in two cases (delete and insertParagraph) we're actually trying to outdent
    the list item.  TODO: there might be a better way to do this.

    <p>If <var title="">node</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code>, and it is not an
    <a href=#allowed-child>allowed child</a> of any of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same
    editing host</a>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">node</var> to
    the <a href=#default-single-line-container-name>default single-line container name</a> and let <var title="">node</var>
    be the result.

    <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">node</var>.

    <li>Return true.
  </ol>

  <li>
  <p class=comments>By this point, we're almost certainly going to merge
  something, and the only question is what.

  <p>Let <var title="">start node</var> equal <var title="">node</var> and let <var title="">start
  offset</var> equal <var title="">offset</var>.

  <li>Repeat the following steps:

  <ol>
    <li>If <var title="">start offset</var> is zero, set <var title="">start offset</var> to the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of <var title="">start node</var> and then set <var title="">start node</var> to
    its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, if <var title="">start node</var> has an <a href=#editable>editable</a>
    <a href=#invisible>invisible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start offset</var>
    minus one, remove it from <var title="">start node</var> and subtract one from
    <var title="">start offset</var>.

    <li>Otherwise, break from this loop.
  </ol>

  <li>
  <p class=comments>At the beginning of an indented block, outdent it, similar
  to a list item.  Browsers don't do this, word processors do.  Note: this
  copy-pastes from the outdent command action.

  <p>If <var title="">offset</var> is zero, and <var title="">node</var> has an
  <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestor</a> <a href=#in-the-same-editing-host>in the same editing
  host</a> that's an <a href=#indentation-element>indentation element</a>:

  <ol>
    <li><a href=#block-extend>Block-extend</a> the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> and
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> are both (<var title="">node</var>, 0), and let <var title="">new range</var> be
    the result.

    <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

    <li>For each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">current node</var> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new
    range</var>, append <var title="">current node</var> to <var title="">node list</var> if the
    last member of <var title="">node list</var> (if any) is not an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of
    <var title="">current node</var>, and <var title="">current node</var> is
    <a href=#editable>editable</a> but has no <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendants</a>.

    <li><a href=#outdent>Outdent</a> each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> in <var title="">node list</var>.

    <li>Return true.
  </ol>

  <li>
  <div class=comments>
  <p>This is to avoid stripping a line break from

    <pre>foo&lt;br&gt;&lt;br&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;[]bar&lt;/table&gt;</pre>

  <p>and similarly for &lt;hr&gt;.  We should just do nothing here.
  </div>

  <p>If the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">start node</var> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start
  offset</var> is a <code class=external data-anolis-spec=html title="the table element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-table-element>table</a></code>, return true.

  <li>
  <p class=comments>If you try backspacing into a table, select it.  This
  doesn't match any browser; it matches the recommendation of the "behavior
  when typing in contentEditable elements" document.  The idea is that then you
  can delete it with a second backspace.

  <p>If <var title="">start node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start
  offset</var> &minus; 1, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the table element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-table-element>table</a></code>:

  <ol>
    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>
    &minus; 1)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Return true.
  </ol>

  <li>
  <div class=comments>
  <p>Special case:

<pre>&lt;p&gt;foo&lt;/p&gt;&lt;br&gt;&lt;p&gt;[]bar&lt;/p&gt;
-&gt; &lt;p&gt;foo&lt;/p&gt;&lt;p&gt;[]bar&lt;/p&gt;</pre>

  <p>and likewise for &lt;hr&gt;.  But with &lt;img&gt; we merge like in other cases:

<pre>&lt;p&gt;foo&lt;/p&gt;&lt;img&gt;&lt;p&gt;[]bar&lt;/p&gt;
-&gt; &lt;p&gt;foo&lt;/p&gt;&lt;img&gt;[]bar.</pre>

  <p>Browsers don't do this consistently.  Firefox 5.0a2 doesn't seem to do it
  at all.
  </div>

  <p>If <var title="">offset</var> is zero; and either the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">start
  node</var> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start offset</var> minus one is an <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-hr-element>hr</a></code>, or
  the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> whose <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> is either a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> or not
  an <a href=#inline-node>inline node</a>:

  <ol>
    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>
    &minus; 1)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li><a href=#delete-the-selection>Delete the selection</a>.

    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
    <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Return true.
  </ol>

  <li>
  <div class=comments>
  <p>If you try backspacing out of a list item, merge it with the previous
  item, but add a line break.  Then you have to backspace again if you really
  want them to be on the same line.  This matches Word 2007 and OpenOffice.org
  3.2.1 Ubuntu, and also matches "behavior when typing in contentEditable
  elements", but does not match any browser.

  <p>Note that this behavior is quite different from what happens if you
  actually select the linebreak in between the two lines.  In that case, the
  blocks are merged as normal.

  <p>Also note that hitting backspace twice will merge with the previous item.
  This matches OO.org, but Word will outdent the item on subsequent backspaces.
  Word's behavior doesn't fit well with the way lists work in HTML, and we
  probably don't want it.
  </div>

  <p>If the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">start node</var> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start
  offset</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code>, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>'s
  <code class=external data-anolis-spec=dom title=dom-Node-firstChild><a href=http://dom.spec.whatwg.org/#dom-node-firstchild>firstChild</a></code> is an <a href=#inline-node>inline node</a>, and <var title="">start offset</var> is
  not zero:

  <ol>
    <li>Let <var title="">previous item</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">start node</var>
    with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start offset</var> minus one.

    <li>
    <p class=comments>If the last child is already a br, we only need to append
    one extra br.  Otherwise we need to append two, since the first will do
    nothing.

    <p>If <var title="">previous item</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> is an <a href=#inline-node>inline
    node</a> other than a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and append the result as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of
    <var title="">previous item</var>.

    <li>If <var title="">previous item</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> is an <a href=#inline-node>inline
    node</a>, call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and
    append the result as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">previous item</var>.
  </ol>

  <li>
  <p class=comments>When merging adjacent list items, make sure we only merge
  the items themselves, not any block children.  We want
  <code title="">&lt;li&gt;&lt;p&gt;foo&lt;li&gt;&lt;p&gt;[]bar</code> to become <code title="">&lt;li&gt;&lt;p&gt;foo&lt;p&gt;[]bar</code>, not
  <code title="">&lt;li&gt;&lt;p&gt;foo&lt;br&gt;[]bar</code> or <code title="">&lt;li&gt;&lt;p&gt;foo[]bar</code>.  To do the
  deletion, we need to wipe out the current selection, so we save it as a
  range.  Saving it as a node/offset pair isn't enough, because it might be
  invalid after we do the deletion.  A range will update according to the range
  mutation rules.

  <p>If <var title="">start node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start
  offset</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code>, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>'s
  <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code> is also an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code>:

  <ol>
    <li>Call <code class=external data-anolis-spec=dom title=dom-Range-cloneRange><a href=http://dom.spec.whatwg.org/#dom-range-clonerange>cloneRange()</a></code> on the <a href=#active-range>active range</a>, and let
    <var title="">original range</var> be the result.

    <li>Set <var title="">start node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start
    offset</var> &minus; 1.

    <li>Set <var title="">start offset</var> to <var title="">start node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.

    <li>Set <var title="">node</var> to <var title="">start node</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>.

    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on
    the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">node</var>, 0)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
    <a href=#concept-selection title=concept-selection>selection</a>.

    <li><a href=#delete-the-selection>Delete the selection</a>.

    <li>Call <code title=dom-Selection-removeAllRanges><a href=#dom-selection-removeallranges>removeAllRanges()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-addRange><a href=#dom-selection-addrange>addRange(<var title="">original range</var>)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
    <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Return true.
  </ol>

  <li>
  <p class=comments>General block-merging case.

  <p>While <var title="">start node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start
  offset</var> minus one:

  <ol>
    <li>If <var title="">start node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">start
    offset</var> minus one is <a href=#editable>editable</a> and <a href=#invisible>invisible</a>,
    remove it from <var title="">start node</var>, then subtract one from <var title="">start
    offset</var>.

    <li>Otherwise, set <var title="">start node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">start offset</var> minus one, then set <var title="">start offset</var> to the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of <var title="">start node</var>.
  </ol>

  <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on
  the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li><a href=#delete-the-selection>Delete the selection</a>, with <var title="">direction</var> "backward".

  <li>Return true.
</ol>


<h3 id=the-formatblock-command><dfn>The <code title="">formatBlock</code> command</dfn></h3>

<p class=note>This command lets you change what block element particular lines
are wrapped in.  It will convert an existing wrapper if one exists, and
otherwise will create a new one.

<p>A <dfn id=formattable-block-name>formattable block name</dfn> is "address", "dd", "div", "dt", "h1",
"h2", "h3", "h4", "h5", "h6", "p", or "pre".

<div class=comments>
<p>Tested browser versions: IE9, Firefox 4.0, Chrome 13 dev, Opera 11.10.

<p>Firefox and Chrome will replace a &lt;blockquote&gt; by a &lt;p&gt; or other given
tag.  IE and Opera will nest the &lt;p&gt; inside instead.  The latter makes more
sense, given that a) we don't support formatBlock with &lt;blockquote&gt; and b)
&lt;blockquote&gt;s are logically different, since they can contain many lines.

<p>Firefox will not convert other tags like &lt;p&gt; to &lt;div&gt;, it will only
wrap unwrapped lines in a &lt;div&gt;.  Firefox also won't replace &lt;div&gt; by
things like &lt;p&gt;, it will nest the &lt;p&gt; inside.  The spec follows other
browsers.

<p>If you try to convert a &lt;dt&gt; to a &lt;div&gt; or &lt;p&gt; or such, Firefox
breaks out of the &lt;dl&gt; entirely, leaving ...&lt;dt&gt;&lt;br&gt;&lt;/dt&gt;&lt;/dl&gt;.
Chrome will convert a &lt;dt&gt; or &lt;dd&gt; to the given element, leaving a
&lt;div&gt; or &lt;p&gt; or such as the child of a &lt;dl&gt;.  I follow IE/Opera, which
only affect the contents of &lt;dt&gt;/&lt;dd&gt; (Firefox behaves this way for
&lt;dd&gt; as well, just not &lt;dt&gt;).  This means you can get invalid DOMs like
&lt;dt&gt;&lt;p&gt;foo&lt;p&gt;&lt;/dt&gt;, but they can be serialized as text/html, so I'm
not too fussy.

<p>When it comes to &lt;li&gt;, IE/Opera behave like with &lt;dt&gt;/&lt;dd&gt;, which
is how I behave too.  Firefox apparently refuses to do anything.  Chrome tries
to wrap the parent list element, breaking it up if only some of the children
are selected; this produces unserializable DOMs if you're wrapping with &lt;p&gt;.

<p>When you're converting multiple blocks at once, Chrome replaces them all by
one block with &lt;br&gt; stuck in, like &lt;p&gt;foo&lt;/p&gt;&lt;p&gt;bar&lt;/p&gt; -&gt;
&lt;div&gt;foo&lt;br&gt;bar&lt;/div&gt;.  It wipes out intervening block containers too
in some cases.  This might make sense for &lt;address&gt;/&lt;h*&gt;/&lt;pre&gt;, but
other browsers don't do it.
</div>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>:

<ol>
  <li>
  <p class=comments>IE9 requires the brackets.  If they're not provided, it
  does nothing.

  <p>If <var title="">value</var> begins with a "&lt;" character and ends with a "&gt;"
  character, remove the first and last characters from it.

  <li>Let <var title="">value</var> be <a class=external data-anolis-spec=domcore href=http://dom.spec.whatwg.org/#converted-to-ascii-lowercase>converted to
  ASCII lowercase</a>.

  <li>
  <div class=comments>
  <p>Opera 11.10 throws NOT_SUPPORTED_ERR for bad elements, all other tested
  browsers ignore the input.  Testing in IE9, Firefox 4.0, Chrome 13 dev, and
  Opera 11.10, supported elements seem to be:

  <dl>
    <dt>Everyone
    <dd>address, div, h*, p, pre

    <dt>Everyone but IE
    <dd>blockquote

    <dt>Everyone but Opera
    <dd>dd, dt

    <dt>IE only
    <dd>dir, menu, ol, ul

    <dt>Firefox and Chrome only
    <dd>dl

    <dt>Chrome only
    <dd>article, aside, footer, header, hgroup, nav, section
  </dl>

  <p>HTML5 as of May 2011 supports: address, article, aside, blockquote, div,
  footer, h*, header, hgroup, nav, p, pre, section, which exactly matches
  Chrome except minus dd/dt/dl.

  <p>See <a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/031765.html>mailing
  list discussion</a> on the subject.
  </div>

  <p>If <var title="">value</var> is not a <a href=#formattable-block-name>formattable block name</a>, return
  false.

  <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>Let <var title="">node list</var> be an empty list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>.

  <li>For each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var>,
  append <var title="">node</var> to <var title="">node list</var> if it is
  <a href=#editable>editable</a>, the last member of <var title="">original node list</var> (if
  any) is not an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>, <var title="">node</var> is either a
  <a href=#non-list-single-line-container>non-list single-line container</a> or an <a href=#allowed-child>allowed child</a>
  of "p" or a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code>, and <var title="">node</var> is not the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of
  a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>.

  <li><a href=#record-the-values>Record the values</a> of <var title="">node list</var>, and let
  <var title="">values</var> be the result.

  <li>
  <p class=comments>This tries to avoid misnesting if only some lines of an
  element are selected, so &lt;h1&gt;[foo]&lt;br&gt;bar&lt;/h1&gt; becomes
  &lt;p&gt;[foo]&lt;/p&gt;&lt;h1&gt;bar&lt;/h1&gt; instead of
  &lt;h1&gt;&lt;p&gt;[foo]&lt;/p&gt;&lt;br&gt;bar&lt;/h1&gt; or such.  It tries to
  heuristically distinguish between divs used as line-breakers and divs used as
  actual wrappers by checking if they have prohibited paragraph children as
  descendants.  It works for address too, in case there are paragraphs nested
  inside.  Thus &lt;address&gt;[foo]&lt;br&gt;bar&lt;/address&gt; becomes
  &lt;p&gt;[foo]&lt;/p&gt;&lt;address&gt;bar&lt;/address&gt;, but
  &lt;address&gt;[foo]&lt;p&gt;bar&lt;/p&gt;&lt;/address&gt; becomes
  &lt;address&gt;&lt;p&gt;[foo]&lt;/p&gt;&lt;p&gt;bar&lt;/p&gt;&lt;/address&gt;.  Likewise, we
  don't break things out of lists or tables or such if they happen to be nested
  in a &lt;div&gt;.

  <p>For each <var title="">node</var> in <var title="">node list</var>, while <var title="">node</var>
  is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of an <a href=#editable>editable</a> <a href=#html-element>HTML element</a>
  <a href=#in-the-same-editing-host>in the same editing host</a>, whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is a
  <a href=#formattable-block-name>formattable block name</a>, and which is not the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a
  <a href=#prohibited-paragraph-child>prohibited paragraph child</a>, <a href=#split-the-parent>split the parent</a> of the
  one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of <var title="">node</var>.

  <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.

  <li>
  <div class=comments>
  <p>We have two different behaviors, one for div and p and one for everything
  else.  The basic difference is that for div and p, we assume that it should
  be one line per element, while for other elements, we put in multiple lines
  separated by &lt;br&gt;.  So if you do formatBlock to p on
    <pre>&lt;div&gt;foo&lt;/div&gt;&lt;div&gt;bar&lt;/div&gt;</pre>
  <p>or
    <pre>foo&lt;br&gt;bar</pre>
  <p>you get
    <pre>&lt;p&gt;foo&lt;/p&gt;&lt;p&gt;bar&lt;/p&gt;</pre>
  <p>but formatBlock to h1 will get you
    <pre>&lt;h1&gt;foo&lt;br&gt;bar&lt;/h1&gt;.</pre>
  <p>IE9 will just change the elements as they are, so it gives
  &lt;p&gt;foo&lt;/p&gt;&lt;p&gt;bar&lt;/p&gt; and &lt;h1&gt;foo&lt;/h1&gt;&lt;h1&gt;bar&lt;/h1&gt; for
  &lt;div&gt;foo&lt;/div&gt;&lt;div&gt;bar&lt;/div&gt;, but &lt;p&gt;foo&lt;br&gt;bar&lt;/p&gt; and
  &lt;h1&gt;foo&lt;br&gt;bar&lt;/h1&gt; for foo&lt;br&gt;bar.  This is unreasonable,
  because the two possible inputs here look identical to the user and might
  have been produced by identical user input.

  <p>Firefox 5.0a2 will give results like &lt;p&gt;foo&lt;/p&gt;&lt;p&gt;bar&lt;/p&gt; or
  &lt;h1&gt;foo&lt;/h1&gt;&lt;h1&gt;bar&lt;/h1&gt; no matter what (modulo oddities in its
  handling of divs).  Opera 11.10 is similar, except it leaves a trailing
  &lt;br&gt; in the first element.

  <p>Chrome 13 dev will give results like &lt;p&gt;foo&lt;br&gt;bar&lt;/p&gt; or
  &lt;h1&gt;foo&lt;br&gt;bar&lt;/h1&gt; no matter what.

  <p>The specced behavior is a compromise between the existing behaviors,
  predicated on the fact that &lt;h1&gt;foo&lt;/h1&gt;&lt;h1&gt;bar&lt;/h1&gt; almost never
  makes sense, and &lt;p&gt;foo&lt;br&gt;bar&lt;/p&gt; isn't usually what's wanted
  either.
  </div>

  <p>While <var title="">node list</var> is not empty:

  <ol>
    <li>If the first member of <var title="">node list</var> is a <a href=#single-line-container>single-line
    container</a>:

    <ol>
      <li>
      <div class=comments>
      <p>If you try to format a single-line container with no children, IE10PP2
      inserts an nbsp before formatting.  (It uses nbsp instead of &lt;br&gt; to
      make blocks not collapse, so the equivalent for us would be to insert a
      &lt;br&gt;.) Firefox 7.0a2 and Opera 11.50 make the element disappear.
      Chrome 14 dev leaves it alone and doesn't format it.  I follow
      Firefox/Opera just because it's the simplest given how I happen to have
      written the spec, and it's a corner case, so exact behavior isn't
      important.

      <p>For blocks that contain only a collapsed whitespace node, IE10PP2 and
      Firefox 7.0a2 convert them like normal.  Chrome 14 dev and Opera 11.50
      leave it alone and don't format it.  I go with the majority, which is
      again simpler to spec.
      </div>

      <p>Let <var title="">sublist</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> of the first member of
      <var title="">node list</var>.

      <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
      <var title="">values</var> be the result.

      <li>Remove the first member of <var title="">node list</var> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>,
      <a href=#preserving-its-descendants>preserving its descendants</a>.

      <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.

      <li>Remove the first member from <var title="">node list</var>.
    </ol>

    <li>Otherwise:

    <ol>
      <li>Let <var title="">sublist</var> be an empty list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>.

      <li>Remove the first member of <var title="">node list</var> and append it to
      <var title="">sublist</var>.

      <li>While <var title="">node list</var> is not empty, and the first member of
      <var title="">node list</var> is the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> of the last member of
      <var title="">sublist</var>, and the first member of <var title="">node list</var> is not a
      <a href=#single-line-container>single-line container</a>, and the last member of
      <var title="">sublist</var> is not a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, remove the first member of <var title="">node
      list</var> and append it to <var title="">sublist</var>.
    </ol>

    <li><a href=#wrap>Wrap</a> <var title="">sublist</var>.  If <var title="">value</var> is "div" or
    "p", <var title="">sibling criteria</var> returns false; otherwise it returns true
    for an <a href=#html-element>HTML element</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> <var title="">value</var> and no
    attributes, and false otherwise.  <var title="">New parent instructions</var>
    return the result of running <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">value</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.  Then <a href=#fix-disallowed-ancestors>fix disallowed ancestors</a> of the
    result.
  </ol>

  <li>Return true.
</ol>

<p class=comments>Firefox 6.0a2 throws, Chrome 14 dev always returns false,
Opera 11.11 doesn't support indeterm to start with, IE9 was uncooperative in
testing so I'm not sure what it does.  I'm speccing it just because it makes
sense.

<p><a href=#indeterminate>Indeterminate</a>:

<ol>
  <li>If the <a href=#active-range>active range</a> is null, return the empty string.

  <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>Let <var title="">node list</var> be all <a href=#visible>visible</a>
  <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> that are <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new
  range</var> and have no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>.

  <li>If <var title="">node list</var> is empty, return false.

  <li>Let <var title="">type</var> be null.

  <li>For each <var title="">node</var> in <var title="">node list</var>:

  <ol>
    <li>While <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#editable>editable</a> and
    <a href=#in-the-same-editing-host>in the same editing host</a> as <var title="">node</var>, and
    <var title="">node</var> is not an <a href=#html-element>HTML element</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a>
    is a <a href=#formattable-block-name>formattable block name</a>, set <var title="">node</var> to its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Let <var title="">current type</var> be the empty string.

    <li>If <var title="">node</var> is an <a href=#editable>editable</a> <a href=#html-element>HTML
    element</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is a <a href=#formattable-block-name>formattable block
    name</a>, and <var title="">node</var> is not the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a
    <a href=#prohibited-paragraph-child>prohibited paragraph child</a>, set <var title="">current type</var> to
    <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a>.

    <li>If <var title="">type</var> is null, set <var title="">type</var> to <var title="">current
    type</var>.

    <li>Otherwise, if <var title="">type</var> does not equal <var title="">current type</var>,
    return true.
  </ol>

  <li>Return false.
</ol>

<div class=comments>
<p>IE9 returns human-readable strings like "Normal" (p/div/etc.), "Formatted"
(pre), "Heading 1" (h1), etc.  Firefox 6.0a2 and Chrome 14 dev both return the
appropriate tag name in lowercase, or the empty string if there is no
appropriate tag.  Opera 11.11 behaves the same, but with uppercase.

<p>IE9 looks like it recognizes address, h*, pre, dd, dt, ol, ul, and dir, with
everything else registering as "Normal".  Firefox 6.0a2 recognizes only the
arguments it accepts for formatBlock, namely address, h*, p, and pre.  Chrome
14 dev recognizes address, div, h*, dd, dl, dt, p, pre plus lots of random
other stuff like blockquote and section.  I'll go with everything that
execCommand("formatblock") accepts as an argument, which at the time of this
writing means what Firefox supports plus div.
</div>

<p><a href=#value>Value</a>:
<ol>
  <li>If the <a href=#active-range>active range</a> is null, return the empty string.

  <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>Let <var title="">node</var> be the first <a href=#visible>visible</a>
  <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var>
  and has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>.  If there is no such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, return the empty
  string.

  <li>
  <p class=comments>Opera 11.11 doesn't require it be editable, so it will
  return "DIV" instead of "" for &lt;div contenteditable&gt;foo&lt;/div&gt;.

  <p>While <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#editable>editable</a> and <a href=#in-the-same-editing-host>in
  the same editing host</a> as <var title="">node</var>, and <var title="">node</var> is not
  an <a href=#html-element>HTML element</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is a <a href=#formattable-block-name>formattable block
  name</a>, set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>
  <div class=comments>
  <p>Chrome 14 dev will report "div" for
  &lt;div&gt;&lt;ol&gt;&lt;li&gt;foo&lt;/ol&gt;&lt;/div&gt; or such.  Opera 11.11 reports "".
  IE and Firefox didn't cooperate with testing.  Opera makes more sense, and
  matches the fact that formatBlock now doesn't recognize such a div as a
  formatBlock candidate, so Opera it is.

  <p>We don't really need to specify "editable" here, since it has to be
  editable if we got to this point.
  </div>

  <p>If <var title="">node</var> is an <a href=#editable>editable</a> <a href=#html-element>HTML element</a>
  whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is a <a href=#formattable-block-name>formattable block name</a>, and
  <var title="">node</var> is not the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of a <a href=#prohibited-paragraph-child>prohibited paragraph
  child</a>, return <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a>, <a class=external data-anolis-spec=domcore href=http://dom.spec.whatwg.org/#converted-to-ascii-lowercase>converted to ASCII lowercase</a>.

  <li>Return the empty string.
</ol>


<h3 id=the-forwarddelete-command><dfn>The <code title="">forwardDelete</code> command</dfn></h3>

<p class=note>This is the same as hitting the delete key (see <a href=#additional-requirements>Additional requirements</a>).  It behaves much
the same as <a href=#the-delete-command>the <code title="">delete</code> command</a>, except of
course backwards.  Also, some of the special cases for backspacing don't apply,
as noted in the comments.  The one special case you get when deleting forward
but not backward is that if the cursor is before a grapheme cluster that
consists of multiple characters, like a base character with combining
diacritics, we delete the diacritics too.  (Backspacing just deletes the last
diacritic, so you have to backspace several times to remove the whole cluster.)

<p><a href=#preserves-overrides>Preserves overrides</a>

<p class=comments>Copy-pasted from delete, see there for comments.

<p><a href=#action>Action</a>:

<ol>
  <li>If the <a href=#active-range>active range</a> is not <code class=external data-anolis-spec=dom title=dom-Range-collapsed><a href=http://dom.spec.whatwg.org/#dom-range-collapsed>collapsed</a></code>, <a href=#delete-the-selection>delete
  the selection</a> and return true.

  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>.

  <li>Let <var title="">node</var> and <var title="">offset</var> be the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>.

  <li>Repeat the following steps:

  <ol>
    <li>If <var title="">offset</var> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of <var title="">node</var> and
    <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> is an <a href=#editable>editable</a>
    <a href=#invisible>invisible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, remove <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>
    from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, if <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var> and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is an <a href=#editable>editable</a>
    <a href=#invisible>invisible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, remove that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> from
    <var title="">node</var>.

    <li>Otherwise, if <var title="">offset</var> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of
    <var title="">node</var> and <var title="">node</var> is an <a href=#inline-node>inline node</a>, or if
    <var title="">node</var> is <a href=#invisible>invisible</a>, set <var title="">offset</var> to one
    plus the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of <var title="">node</var>, then set <var title="">node</var> to its
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>
    <p class=comments>No special link behavior for forwardDelete here, unlike
    delete.

    <p>Otherwise, if <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">offset</var> and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is neither a <a href=#block-node>block node</a>
    nor a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> nor an <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#the-img-element>img</a></code> nor a <a href=#collapsed-block-prop>collapsed block prop</a>, set
    <var title="">node</var> to that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, then set <var title="">offset</var> to zero.

    <li>Otherwise, break from this loop.
  </ol>

  <li>If <var title="">node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and <var title="">offset</var> is not
  <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>:

  <ol>
    <li>Let <var title="">end offset</var> be <var title="">offset</var> plus one.

    <li>
    <div class=comments>
    <p>Firefox 7.0a2, Chrome 14 dev, Word 2007, and OpenOffice.org 3.2.1 Ubuntu
    act as the spec says, getting rid of all diacritics on forward delete.  IE9
    and Opera 11.50 have no special case and just delete the next character.  I
    go with Firefox/Chrome/Word/OO.

    <p>However, when I actually type in the text box as opposed to running
    semi-automated tests, IE9 has magical behavior: it replaces the base
    character with something that looks like &#x25cc; U+25CC DOTTED CIRCLE.
    Further strikes of the delete key remove the diacritics, and the circle
    vanishes along with the last of them.  I wasn't able to get it to actually
    replace the base character, so I'm not sure what the point is.  The circle
    doesn't seem to appear in the DOM, and apparently it disappears in some
    circumstances.  This might be worth standardizing somehow, I don't know.

    <p>TODO: The way we remove diacritics is probably not right.  We probably
    want to normalize to grapheme cluster boundaries, using UAX#29 or
    something.  We also need to handle non-BMP stuff.  The idea is that if the
    cursor is before a character that precedes a combining mark, you need to
    delete the combining mark too.
    </div>

    <p>While <var title="">end offset</var> is not <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> and the
    <var title="">end offset</var>th <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> of <var title="">node</var>'s <code class=external data-anolis-spec=dom title=dom-CharacterData-data><a href=http://dom.spec.whatwg.org/#dom-characterdata-data>data</a></code> has
    general category M when interpreted as a Unicode code point, add one to
    <var title="">end offset</var>.

    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">node</var>, <var title="">end offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li><a href=#delete-the-selection>Delete the selection</a>.

    <li>Return true.
  </ol>

  <li>If <var title="">node</var> is an <a href=#inline-node>inline node</a>, return true.

  <li>If <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">offset</var> and
  that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> or <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the img element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#the-img-element>img</a></code>, but is not a
  <a href=#collapsed-block-prop>collapsed block prop</a>:

  <ol>
    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">node</var>, <var title="">offset</var> + 1)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li><a href=#delete-the-selection>Delete the selection</a>.

    <li>Return true.
  </ol>

  <li>
  <p class=comments>No special list-item behavior for forwardDelete here,
  unlike delete.

  <p>Let <var title="">end node</var> equal <var title="">node</var> and let <var title="">end
  offset</var> equal <var title="">offset</var>.

  <li>If <var title="">end node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end
  offset</var>, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a <a href=#collapsed-block-prop>collapsed block prop</a>, add
  one to <var title="">end offset</var>.

  <li>Repeat the following steps:

  <ol>
    <li>If <var title="">end offset</var> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of <var title="">end node</var>, set
    <var title="">end offset</var> to one plus the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of <var title="">end node</var> and
    then set <var title="">end node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>Otherwise, if <var title="">end node</var> has an <a href=#editable>editable</a>
    <a href=#invisible>invisible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end offset</var>,
    remove it from <var title="">end node</var>.

    <li>Otherwise, break from this loop.
  </ol>

  <li>
  <p class=comments>No special indentation element behavior for forwardDelete
  here, unlike delete.

  <p>If the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">end node</var> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end
  offset</var> minus one is a <code class=external data-anolis-spec=html title="the table element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-table-element>table</a></code>, return true.

  <li>If the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">end node</var> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end
  offset</var> is a <code class=external data-anolis-spec=html title="the table element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-table-element>table</a></code>:

  <ol>
    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var> + 1)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Return true.
  </ol>

  <li>
  <p class=comments>Note, any br will do here: a br immediately after a block
  is always significant.

  <p>If <var title="">offset</var> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of <var title="">node</var>, and the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">end node</var> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end offset</var> is an
  <code class=external data-anolis-spec=html title="the hr element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-hr-element>hr</a></code> or <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>:

  <ol>
    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var> + 1)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li><a href=#delete-the-selection>Delete the selection</a>.

    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
    <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Return true.
  </ol>

  <li>
  <p class=comments>No special list-item behavior for forwardDelete here,
  unlike delete.

  <p>While <var title="">end node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end
  offset</var>:

  <ol>
    <li>If <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> <var title="">end offset</var>
    is <a href=#editable>editable</a> and <a href=#invisible>invisible</a>, remove it from
    <var title="">end node</var>.

    <li>Otherwise, set <var title="">end node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> with <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>
    <var title="">end offset</var> and set <var title="">end offset</var> to zero.
  </ol>

  <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li><a href=#delete-the-selection>Delete the selection</a>.
</ol>


<h3 id=the-indent-command><dfn>The <code title="">indent</code> command</dfn></h3>

<div class=comments>
<dl>
  <dt>IE9
  <dd>Outputs &lt;blockquote style="margin-right: 0px" dir="ltr"&gt;, or when
  surrounding RTL blocks, &lt;blockquote style="margin-left: 0px" dir="rtl"&gt;.
  The direction seems to go by the end of the selection.  The presence of the
  dir attribute means that any contents that were inheriting a different dir
  from an ancestor get their direction changed as a side effect, but if they
  actually have the opposite dir specified, they won't appear to be indented.
  It doesn't reset top or bottom margins on the blockquote, so it adds them.
  If it's not wrapping a block element, like if it's only wrapping up until a
  &lt;br&gt;, it adds a &lt;p&gt;.

  <dt>Firefox 4.0
  <dd>In styleWithCSS mode, adds style="margin-left: 40px" to the appropriate
  block container (or margin-right if it's RTL).  If there's no appropriate
  block container, adds a div.  If multiple blocks are affected, it goes by the
  direction of the block whose style it's changing, which winds up being wrong
  for descendants with different direction.  In non-styleWithCSS mode, uses
  &lt;blockquote&gt;, so it indents on both sides and also adds top/bottom
  margins.

  <dt>Chrome 12 dev
  <dd>Outputs &lt;blockquote class="webkit-indent-blockquote" style="margin: 0
  0 0 40px; border: none; padding: 0px"&gt; in both modes for both LTR and RTL
  (which is broken for RTL, since it indents only on the left).

  <dt>Opera 11.00
  <dd>Outputs &lt;blockquote&gt;, so it indents on both sides and on the
  top/bottom.
</dl>

<p>For repeated indentation, everyone except Opera that outputs
&lt;blockquote&gt;s just puts them at the outermost possible location, which works
well.  Opera puts them in the innermost position, which is broken, because it
will even put them inside &lt;p&gt; (which will not round-trip through text/html
serialization).

<p>Gecko in CSS mode messes up by adding margins even to things like
&lt;blockquote&gt; that already have margins from CSS rules, instead of nesting a
div, so it doesn't actually increase the indentation.  However, if an element
has an explicit left margin (assuming LTR), it will increase the margin to
80px, so it works with WebKit's blockquotes.

<p>We have two strategies for handling directionality: always indent on both
sides (Firefox non-CSS, Opera) or try to figure out heuristically which side we
want (IE, Firefox CSS).  The latter approach is only possible by adding extra
markup and complexity, so for now we'll take the easy way out and go with just
indenting on both sides.

<p>This reasoning doesn't discuss lists.  For research on lists, see the
comment for <a href=#the-insertorderedlist-command>insertOrderedList</a>.  List
handling is more complicated and I wound up differing from all browsers in lots
of ways.
</div>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>:

<ol>
  <li>Let <var title="">items</var> be a list of all <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>s that are
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestors</a> of the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>
  and/or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>.

  <li>
  <p class=comments>TODO: This overnormalizes, but it seems like the simplest
  solution for now.

  <p>For each <var title="">item</var> in <var title="">items</var>, <a href=#normalize-sublists>normalize
  sublists</a> of <var title="">item</var>.

  <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

  <li>For each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var>,
  if <var title="">node</var> is <a href=#editable>editable</a> and is an <a href=#allowed-child>allowed
  child</a> of "div" or "ol" and if the last member of <var title="">node list</var>
  (if any) is not an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>, append <var title="">node</var> to
  <var title="">node list</var>.

  <li>
  <p class=comments>Without this step, the last child of the previous sibling
  might be a list, which the li wouldn't get appended to.

  <p>If the first <a href=#visible>visible</a> member of <var title="">node list</var> is an
  <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>:

  <ol>
    <li>Let <var title="">sibling</var> be <var title="">node list</var>'s first
    <a href=#visible>visible</a> member's <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code>.

    <li>While <var title="">sibling</var> is <a href=#invisible>invisible</a>, set
    <var title="">sibling</var> to its <code class=external data-anolis-spec=dom title=dom-Node-previousSibling><a href=http://dom.spec.whatwg.org/#dom-node-previoussibling>previousSibling</a></code>.

    <li>If <var title="">sibling</var> is an <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>, <a href=#normalize-sublists>normalize sublists</a> of
    <var title="">sibling</var>.
  </ol>

  <li>While <var title="">node list</var> is not empty:

  <ol>
    <li>Let <var title="">sublist</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

    <li>Remove the first member of <var title="">node list</var> and append it to
    <var title="">sublist</var>.

    <li>While the first member of <var title="">node list</var> is the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>
    of the last member of <var title="">sublist</var>, remove the first member of
    <var title="">node list</var> and append it to <var title="">sublist</var>.

    <li><a href=#indent>Indent</a> <var title="">sublist</var>.
  </ol>
</ol>


<h3 id=the-inserthorizontalrule-command><dfn>The <code title="">insertHorizontalRule</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p class=comments>You'd think interop here would be simple, right?  Nope: we
have three different behaviors across four browsers.  Opera 11.00 is the only
one that acts more or less like the spec.  IE9 and Chrome 12 dev treat the
value as an id, which is weird and probably useless, so I don't do it.  Firefox
4.0 produces &lt;hr size=2 width=100%&gt; instead of &lt;hr&gt;, which is also weird
and almost definitely useless, so I don't do it.  Then you have the varying
behavior in splitting up parents to ensure validity . . .

<p><a href=#action>Action</a>:

<ol>
  <li>Let <var title="">start node</var>, <var title="">start offset</var>, <var title="">end node</var>,
  and <var title="">end offset</var> be the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>
  and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offsets</a>.

  <li>While <var title="">start offset</var> is 0 and <var title="">start node</var>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set <var title="">start offset</var> to <var title="">start
  node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">start node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>While <var title="">end offset</var> is <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, and
  <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is not null, set <var title="">end offset</var> to
  one plus <var title="">end node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>, then set <var title="">end node</var> to its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">start node</var>, <var title="">start offset</var>)</a></code> on
  the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">end node</var>, <var title="">end offset</var>)</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li><a href=#delete-the-selection>Delete the selection</a>, with <var title="">block merging</var> false.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is neither
  <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, return true.

  <li>
  <p class=comments>We don't want to call insertNode at the start or end of a
  text node, because that will leave an empty text node.

  <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and
  its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is zero, call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
  <a href=#concept-selection title=concept-selection>selection</a>, with first argument the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> and second argument the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and
  its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, call
  <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>, with first
  argument the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>, and the
  second argument one plus the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>.

  <li>Let <var title="">hr</var> be the result of calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("hr")</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

  <li>Run <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">hr</var>)</a></code> on the <a href=#active-range>active range</a>.

  <li>
  <p class=comments>IE9 and Chrome 13 dev seem to never break up any ancestors,
  which can lead to unserializable DOMs like &lt;hr&gt; inside &lt;p&gt;.  Opera
  11.11 seems to always break up parents going all the way up to the
  contenteditable root, even ones like &lt;div&gt; that can contain &lt;hr&gt;.
  Firefox 5.0a2 acts the most sensibly: it only breaks up things like &lt;p&gt; or
  &lt;b&gt; that shouldn't contain &lt;hr&gt;.  The spec goes with Firefox here
  (although the list of what to break up isn't precisely identical).

  <p><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">hr</var>.

  <li>Run <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>, with first
  argument <var title="">hr</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> and the second argument equal to one plus
  <var title="">hr</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>.

  <li>Return true.
</ol>


<h3 id=the-inserthtml-command><dfn>The <code title="">insertHTML</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<div class=comments>
<p>Not supported by IE9.  Handling of disallowed children is interesting:

<dl>
  <dt>Firefox 5.0a2
  <dd>Will allow &lt;dt&gt; inside &lt;dt&gt; (doesn't serialize).  If you try
  inserting dir/ol/ul inside an existing dir/ol/ul, it will strip the list
  element and leave only the li's, so inserting &lt;ul&gt;&lt;li&gt;abc&lt;/ul&gt; into
  &lt;ol&gt;&lt;li&gt;f[o]o&lt;/ol&gt; creates
  &lt;ol&gt;&lt;li&gt;f&lt;li&gt;abc&lt;li&gt;o&lt;/ol&gt;.  &lt;dt&gt;/&lt;dd&gt;/&lt;li&gt; that
  don't descend from a list will be left alone, not converted to &lt;p&gt;.  Empty
  elements seem not to be inserted.  &lt;li&gt; will get put inside &lt;p&gt;, which
  breaks serialization.  Nothing is allowed inside &lt;xmp&gt;, not even text.

  <dt>Chrome 13 dev
  <dd>Inserting a &lt;p&gt; into a &lt;p&gt; or &lt;li&gt; or such will remove the child
  &lt;p&gt;, adding its contents to the parent instead.  Adding an &lt;li&gt; or
  &lt;hr&gt; as the child of a &lt;p&gt; works, as does an &lt;a&gt; inside an &lt;a&gt;,
  &lt;h2&gt; inside &lt;h1&gt;, &lt;li&gt; inside &lt;li&gt;, &lt;nobr&gt; inside &lt;nobr&gt;,
  &lt;b&gt; inside &lt;xmp&gt;, etc. (all unserializable).  But &lt;dt&gt; and &lt;dd&gt;
  seem to get converted to their contents like &lt;p&gt;.
  &lt;ol&gt;&lt;li&gt;abc&lt;/ol&gt; inside &lt;ol&gt;&lt;li&gt;f[o]o&lt;/ol&gt; becomes
  &lt;ol&gt;&lt;li&gt;f&lt;li&gt;abc&lt;li&gt;&lt;li&gt;o&lt;/ol&gt;, interestingly (note the
  empty &lt;li&gt;).  I don't understand how it works, but it doesn't seem to make
  much sense.

  <dt>Opera 11.11
  <dd>Seems to do almost no validity or serialization checks, except that it
  prevents &lt;a&gt; inside &lt;a&gt;, &lt;nobr&gt; inside &lt;nobr&gt;, and block elements
  inside inline elements.  Interestingly, most of the places where it's
  non-serializable per HTML parsing are actually serializable in Opera's own
  parser.
</dl>
</div>

<p><a href=#action>Action</a>:

<ol>
  <li>
  <div class=comments>
  <p>Chrome 14 dev and Opera 11.11 do this even if the value is empty.  Firefox
  5.0a2 throws an exception.

  <p>Firefox 7.0a2 and Chrome 14 dev do strip wrappers here, so inserting HTML
  in the place of &lt;b&gt;[foo]&lt;/b&gt; will remove the &lt;b&gt;.  Opera 11.50 keeps
  the wrappers.  I follow the majority and leave the "strip wrappers" flag
  true.
  </div>

  <p><a href=#delete-the-selection>Delete the selection</a>.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is neither
  <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, return true.

  <li>
  <p class=comments>TODO: This has some interesting consequences.  For
  instance, table cells and similar will just vanish if they're not in an
  appropriate place; and inside a script or style or xmp or such, the argument
  will effectively be HTML-escaped before use.  Some of these consequences
  might be undesirable.

  <p>Let <var title="">frag</var> be the result of calling <code class=external data-anolis-spec=domps title=dom-Range-createContextualFragment><a href=http://domparsing.spec.whatwg.org/#dom-range-createcontextualfragment>createContextualFragment(<var title="">value</var>)</a></code>
  on the <a href=#active-range>active range</a>.

  <li>Let <var title="">last child</var> be the <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> of <var title="">frag</var>.

  <li>
  <p class=comments>Firefox 5.0a2 also seems to not add empty elements like
  &lt;b&gt;&lt;/b&gt;, but Chrome 13 dev and Opera 11.11 do.

  <p>If <var title="">last child</var> is null, return true.

  <li>Let <var title="">descendants</var> be all <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendants</a> of <var title="">frag</var>.

  <li>
  <div class=comments>
  <p>This is so we don't get something like
<pre>&lt;div&gt;[foo]&lt;/div&gt;
-&gt; &lt;div&gt;{}&lt;br&gt;&lt;/div&gt;
-&gt; &lt;div&gt;&lt;p&gt;Some HTML{}&lt;/p&gt;&lt;br&gt;&lt;/div&gt;</pre>
  <p>with an extra bogus line break at the end.
  </div>

  <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is a <a href=#block-node>block
  node</a>:

  <ol>
    <li>Let <var title="">collapsed block props</var> be all <a href=#editable>editable</a>
    <a href=#collapsed-block-prop>collapsed block prop</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> of the <a href=#active-range>active
    range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> that have <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> greater than or equal to
    the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a>.

    <li>For each <var title="">node</var> in <var title="">collapsed block props</var>, remove
    <var title="">node</var> from its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.
  </ol>

  <li>
  <p class=comments>We could canonicalize whitespace after inserting the
  fragment, but let's not.  If the author wants HTML, give them HTML behavior.
  When asked to replace a paragraph's contents with a single space, Firefox
  7.0a2 does so but inserts a &lt;br&gt; before it (not after); Chrome 14 dev does
  so and doesn't insert a &lt;br&gt;, so the paragraph collapses; Opera 11.50
  doesn't insert the space at all, and just inserts a &lt;br&gt;.  Correct
  behavior is to insert a space, then insert a &lt;br&gt; after it in the next
  step because it's an invisible node.

  <p>Call <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">frag</var>)</a></code> on the <a href=#active-range>active range</a>.

  <li>
  <p class=comments>In case we remove all the contents, then remove the extra
  &lt;br&gt;, then only add a comment or something.  In that case we want to
  re-add the extra &lt;br&gt;.  We don't try fixing the actual inserted content:
  that's the author's lookout.

  <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is a <a href=#block-node>block
  node</a> with no <a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, call
  <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and append the result as the
  last child of the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>.

  <li>
  <p class=comments>Need to do this before fixing disallowed ancestors, since
  otherwise the last child might have been removed (e.g., it's an li).

  <p>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>, with
  <var title="">last child</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> as the first argument and one plus its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> as the second.

  <li>
  <p class=comments>We want to fix all descendants, not just children.
  Consider &lt;div&gt;&lt;li&gt;foo&lt;/li&gt;&lt;/div&gt;, for example.

  <p><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
  <var title="">descendants</var>.

  <li>Return true.
</ol>


<h3 id=the-insertimage-command><dfn>The <code title="">insertImage</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>:

<ol>
  <li>
  <p class=comments>Similar logic to createLink, except even more compelling,
  since an HTML document linking to itself as an image is just silly.  In fact,
  the current HTML spec instructs UAs to not even try displaying the image, and
  just fail immediately if the URL is empty.  Firefox 4b11 silently does
  nothing on an empty string, but the other three browsers I tested stick in
  the &lt;img&gt; anyway.

  <p>If <var title="">value</var> is the empty string, return false.

  <li>
  <p class=comments>Firefox 7.0a2 seems to strip the wrapper or not depending
  on the exact positioning of the selection: &lt;b&gt;{foo}&lt;/b&gt; yes,
  &lt;b&gt;[foo]&lt;/b&gt; no.  Chrome 14 dev seems to strip the wrapper regardless.
  Opera 11.50 seems to keep the wrapper, but place the image outside it.  I
  didn't get IE to cooperate with my tests.  I chose to leave wrappers across
  the board because they might be meaningful: e.g., a background-color when the
  image is small or not fully opaque.

  <p><a href=#delete-the-selection>Delete the selection</a>, with <var title="">strip wrappers</var> false.

  <li>Let <var title="">range</var> be the <a href=#active-range>active range</a>.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is neither
  <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, return true.

  <li>
  <p class=comments>Same logic as with insertHTML.

  <p>If <var title="">range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is a <a href=#block-node>block node</a> whose
  sole <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is 0, remove its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> from it.

  <li>Let <var title="">img</var> be the result of calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("img")</a></code> on
  the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

  <li>
  <p class=comments>No alt text, so it's probably invalid.  This matches all
  browsers.

  <p>Run <code class=external data-anolis-spec=dom title=dom-Element-setAttribute><a href=http://dom.spec.whatwg.org/#dom-element-setattribute>setAttribute("src", <var title="">value</var>)</a></code> on <var title="">img</var>.

  <li>
  <p class=comments>This winds up putting it at the original start point of the
  active range, as currently specced.  This matches IE9 and Firefox 5.0a2.
  Chrome 13 dev puts it at the end point, and Opera 11.11 puts it in between
  (where the range would collapse if you called deleteContents()).

  <p>Run <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">img</var>)</a></code> on <var title="">range</var>.

  <li>Let <var title="">selection</var> be the result of calling <code title=dom-Document-getSelection><a href=#dom-document-getselection>getSelection()</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

  <li>Run <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on <var title="">selection</var>, with first argument equal
  to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <var title="">img</var> and the second argument equal to one plus
  the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of <var title="">img</var>.

  <li>Return true.
</ol>


<h3 id=the-insertlinebreak-command><dfn>The <code title="">insertLineBreak</code> command</dfn></h3>

<p class=note>This is the same as hitting Shift-Enter or such (see <a href=#additional-requirements>Additional requirements</a>).  It deletes the
selection, and replaces it with a <code title="">&lt;br&gt;</code>.  No real
complications.

<div class=comments>
<p>Only implemented in WebKit (Chrome 14 dev).  Other tests are entirely
manual (i.e., actually hitting Shift-Enter instead of running a command).
There's a surprisingly large amount of interop.

<p>IE9 is tripped up by &lt;xmp&gt;, and also often doesn't add an extra &lt;br&gt;
when the one it just inserted is extraneous.

<p>Firefox 6.0a2 doesn't notice if you're trying to put the &lt;br&gt; in a bad
place, which can result in unserializable DOMs.

<p>Chrome 14 dev inserts a literal linebreak for pre and xmp and maybe other
similar elements.  This doesn't seem very useful, so I don't bother.

<p>Opera 11.11 isn't heedful of &lt;xmp&gt;, and treats &lt;pre&gt; somewhat oddly.
</div>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>:

<ol>
  <li>
  <p class=comments>IE9 doesn't strip wrappers (IE10PP2 didn't work in tests).
  Firefox 7.0a2 strips wrappers inconsistently depending on the exact selection
  endpoints.  Chrome 14 dev strips wrappers but recreates any styles using new
  wrappers.  Opera 11.50 strips all wrappers.

  <p><a href=#delete-the-selection>Delete the selection</a>, with <var title="">strip wrappers</var> false.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is neither
  <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, return true.

  <li>
  <p class=comments>script, xmp, table, . . .

  <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>, and
  "br" is not an <a href=#allowed-child>allowed child</a> of it, return true.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is not an <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code>,
  and "br" is not an <a href=#allowed-child>allowed child</a> of the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>, return true.

  <li>
  <p class=comments>We don't want to call insertNode at the start or end of a
  text node, because that will leave an empty text node.

  <p>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and
  its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is zero, call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
  <a href=#concept-selection title=concept-selection>selection</a>, with first argument equal to the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> and second argument equal to the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and
  its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, call
  <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>, with first
  argument equal to the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>
  and second argument equal to one plus the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a>.

  <li>Let <var title="">br</var> be the result of calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

  <li>Call <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">br</var>)</a></code> on the <a href=#active-range>active range</a>.

  <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>, with
  <var title="">br</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> as the first argument and one plus <var title="">br</var>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> as the second argument.

  <li>If <var title="">br</var> is a <a href=#collapsed-line-break>collapsed line break</a>, call
  <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and let <var title="">extra br</var>
  be the result, then call <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">extra br</var>)</a></code> on the
  <a href=#active-range>active range</a>.

  <li>Return true.
</ol>


<h3 id=the-insertorderedlist-command><dfn>The <code title="">insertOrderedList</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>: <a href=#toggle-lists>Toggle lists</a> with <var title="">tag name</var>
"ol", then return true.

<p class=comments>Firefox 6.0a2 sort of supports this, but it throws exceptions
most of the time.  It has the quirk that even if there are no ol's around, it
will say it's indeterminate if there are some things that are ul's and some
that are not lists at all, but this doesn't make sense and I don't duplicate
it.  No one else supports indeterminate for insert*List, but it makes sense if
you support state.

<p><a href=#indeterminate>Indeterminate</a>: True if the <a href="#selection's-list-state">selection's list state</a>
is "mixed" or "mixed ol", false otherwise.

<p class=comments>IE9 throws exceptions in most cases, Firefox 6.0a2 in some
cases as well, for no apparent reason.  Ignoring those, the spec basically
matches all browsers, except with a few weird random mismatches that looked
like browser bugs to me.

<p><a href=#state>State</a>: True if the <a href="#selection's-list-state">selection's list state</a> is "ol",
false otherwise.


<h3 id=the-insertparagraph-command><dfn>The <code title="">insertParagraph</code> command</dfn></h3>

<div class=note>
<p>This is the same as hitting enter (see <a href=#additional-requirements>Additional requirements</a>).  The general rule
is that we find the nearest <a href=#single-line-container>single-line container</a> ancestor, clone
it and insert the clone after it, and then move all the contents after the
cursor (along with the cursor itself) to the clone.  But there are a few
special cases:

<ul>
  <li>If we can't find a single-line container to use, first we wrap the
  current line in a new container with the <a href=#default-single-line-container-name>default single-line container
  name</a>.

  <li>For <code title="">&lt;address&gt;</code>, <code title="">&lt;listing&gt;</code>, and
  <code title="">&lt;pre&gt;</code>, we add a <code title="">&lt;br&gt;</code> instead of
  cloning it.  These are all elements that are meant to contain multiple lines,
  not have one line per element.

  <li>If the cursor is in a list item with no contents, hitting enter breaks
  out of the list entirely, outdenting the current item.  This means that if
  you're in a list, you can hit enter twice to break out.

  <li>If the cursor is at the end of a heading, hitting enter doesn't make a
  new heading, it switches to the <a href=#default-single-line-container-name>default single-line container
  name</a>.

  <li>If the cursor is at the end of a <code title="">&lt;dt&gt;</code> or <code title="">&lt;dd&gt;</code>, the new element is the opposite type, so you naturally
  switch between entering terms and definitions.
</ul>
</div>

<p><a href=#preserves-overrides>Preserves overrides</a>

<div class=comments>
<p>There are three major behaviors here.  Firefox 5.0a2 behaves identically to
execCommand("formatBlock", false, "p"), which is not really useful.  IE9
actually just overwrites the selection with an empty paragraph element, which
seems not very useful either.  Chrome 13 dev and Opera 11.10 behave basically
the same as if the user hit the Return key.  This latter behavior seems much
more useful, even though it's horribly misnamed, so it's what I'll spec.
Comments about IE/Firefox are based on manual tests, where I hit Enter instead
of running commands.

<p>(Actually, Opera doesn't behave quite the same for insertParagraph and line
breaks.  But it's pretty close, and I expect the differences are bugs.)

<p>Then, of course, we have several flavors of line-breaking behavior to choose
from.  Firefox prefers &lt;br&gt;s, unless it's in the middle of a &lt;p&gt; or
something.  Opera and IE like &lt;p&gt;.  Chrome prefers &lt;div&gt;.  And there are
lots of subtleties besides.  I go with IE/Opera-style behavior, as discussed in
<a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/031577.html>a
whatwg thread</a>.
</div>

<p><a href=#action>Action</a>:

<ol>
  <li><a href=#delete-the-selection>Delete the selection</a>.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is neither
  <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, return true.

  <li>Let <var title="">node</var> and <var title="">offset</var> be the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>.

  <li>If <var title="">node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, and <var title="">offset</var> is neither 0
  nor the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of <var title="">node</var>, call
  <code class=external data-anolis-spec=dom title=dom-Text-splitText><a href=http://dom.spec.whatwg.org/#dom-text-splittext>splitText(<var title="">offset</var>)</a></code> on <var title="">node</var>.

  <li>If <var title="">node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node and <var title="">offset</var> is its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>, set <var title="">offset</var> to one plus the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of
  <var title="">node</var>, then set <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>If <var title="">node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> or <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#comment>Comment</a></code> node, set
  <var title="">offset</var> to the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of <var title="">node</var>, then set
  <var title="">node</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li>Let <var title="">container</var> equal <var title="">node</var>.

  <li>While <var title="">container</var> is not a <a href=#single-line-container>single-line container</a>,
  and <var title="">container</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#editable>editable</a> and <a href=#in-the-same-editing-host>in
  the same editing host</a> as <var title="">node</var>, set <var title="">container</var> to
  its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

  <li>
  <p class=comments><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13841">Bug 13841</a>.

  <p>If <var title="">container</var> is an <a href=#editable>editable</a> <a href=#single-line-container>single-line
  container</a> <a href=#in-the-same-editing-host>in the same editing host</a> as <var title="">node</var>,
  and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is "p" or "div":

  <ol>
    <li>Let <var title="">outer container</var> equal <var title="">container</var>.

    <li>While <var title="">outer container</var> is not a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>,
    and <var title="">outer container</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is <a href=#editable>editable</a>, set
    <var title="">outer container</var> to its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a>.

    <li>If <var title="">outer container</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code> or <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>, set
    <var title="">container</var> to <var title="">outer container</var>.
  </ol>

  <li>
  <p class=comments>We add the default wrapper in this case.

  <p>If <var title="">container</var> is not <a href=#editable>editable</a> or not <a href=#in-the-same-editing-host>in the
  same editing host</a> as <var title="">node</var> or is not a <a href=#single-line-container>single-line
  container</a>:

  <ol>
    <li>Let <var title="">tag</var> be the <a href=#default-single-line-container-name>default single-line container
    name</a>.

    <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let
    <var title="">new range</var> be the result.

    <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

    <li>Append to <var title="">node list</var> the first <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> in <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-order title=concept-tree-order>tree order</a> that
    is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var> and is an <a href=#allowed-child>allowed
    child</a> of "p", if any.

    <li>If <var title="">node list</var> is empty:

    <ol>
      <li>
      <p class=comments>Ideally, we should normalize things so that the cursor
      is never in a weird place after deletion, but let's be safe and bail out
      if we do hit this scenario.  It's not clear if we need this line in the
      long term, but at the time of this writing there's at least one corner
      case where deleting can leave the cursor inside a &lt;tr&gt;.

      <p>If <var title="">tag</var> is not an <a href=#allowed-child>allowed child</a> of
      the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, return true.

      <li>Set <var title="">container</var> to the result of calling
      <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">tag</var>)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

      <li>Call <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">container</var>)</a></code> on the <a href=#active-range>active
      range</a>.

      <li>Call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>, and append the
      result as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">container</var>.

      <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">container</var>, 0)</a></code> on the
      <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

      <li>Return true.
    </ol>

    <li>
    <p class=comments>TODO: It is not at all obvious that this is the correct
    list of nodes in all cases.  It should probably work because of how the
    block-extend algorithm works, but further thought would be good.

    <p>While the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code> of the last member of <var title="">node list</var> is
    not null and is an <a href=#allowed-child>allowed child</a> of "p", append it to
    <var title="">node list</var>.

    <li><a href=#wrap>Wrap</a> <var title="">node list</var>, with <var title="">sibling
    criteria</var> returning false and <var title="">new parent instructions</var>
    returning the result of calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">tag</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.  Set <var title="">container</var> to the result.
  </ol>

  <li>
  <div class=comments>
  <p>IE9 and Chrome 13 dev just break &lt;pre&gt; up into multiple &lt;pre&gt;s.
  Firefox 5.0a2 and Opera 11.10 insert a &lt;br&gt; instead, treating it
  differently from &lt;p&gt;.  The latter makes more sense.  What might make the
  most sense is to just insert an actual newline character, though, since this
  is a pre after all . . .

  <p>IE9 and Chrome 13 dev also break &lt;address&gt; up into multiple
  &lt;address&gt;es.  Firefox 5.0a2 inserts &lt;br&gt; instead.  Opera 11.10 nests
  &lt;p&gt;s inside.  I don't like Opera's behavior, because it means we nest
  formatBlock candidates inside one another, so I'll go with Firefox.

  <p>listing and xmp work the same as pre in all browsers.  For Firefox and
  Opera, this results in trying to put a br inside an xmp, so I go with
  IE/Chrome for xmp.

  <p>TODO: In cases where hitting enter in a header doesn't break out of the
  header, we should probably follow this code path too, instead of creating an
  adjoining header.  No browser does this, though, so we don't.
  </div>

  <p>If <var title="">container</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is "address", "listing", or
  "pre":

  <ol>
    <li>Let <var title="">br</var> be the result of calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on
    the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

    <li>Call <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">br</var>)</a></code> on the <a href=#active-range>active range</a>.

    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var> + 1)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>
    <p class=comments>Necessary because adding a br to the end of a block
    element does nothing if there wasn't one there already.  A single newline
    immediately preceding a block boundary does nothing.

    <p>If <var title="">br</var> is the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of <var title="">container</var>,
    let <var title="">br</var> be the result of calling <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>, then call <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">br</var>)</a></code> on
    the <a href=#active-range>active range</a>.

    <li>Return true.
  </ol>

  <li>
  <p class=comments>Including dt/dd here follows Firefox 5.0a2, as with the
  special dt/dd handling below.

  <p>If <var title="">container</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> is "li", "dt", or "dd"; and
  either it has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a> or it has a single <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>
  is a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>:

  <ol>
    <li><a href=#split-the-parent>Split the parent</a> of the one-<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> list consisting of
    <var title="">container</var>.

    <li>If <var title="">container</var> has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, call
    <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a> and append the result as
    the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">container</var>.

    <li>
    <p class=comments>Annoying hack to prevent the dl from being re-added when
    fixing disallowed ancestors.  In most cases we want a wrapper dl added, but
    in two cases (delete and insertParagraph) we're actually trying to outdent
    the list item.  TODO: there might be a better way to do this.

    <p>If <var title="">container</var> is a <code class=external data-anolis-spec=html title="the dd element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dd-element>dd</a></code> or <code class=external data-anolis-spec=html title="the dt element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dt-element>dt</a></code>, and it is not an
    <a href=#allowed-child>allowed child</a> of any of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestors</a> <a href=#in-the-same-editing-host>in the same
    editing host</a>, <a href=#set-the-tag-name>set the tag name</a> of <var title="">container</var>
    to the <a href=#default-single-line-container-name>default single-line container name</a> and let
    <var title="">container</var> be the result.

    <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of <var title="">container</var>.

    <li>Return true.
  </ol>

  <li>Let <var title="">new line range</var> be a new <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range title=concept-range>range</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> is
  the same as the <a href=#active-range>active range</a>'s, and whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> is
  (<var title="">container</var>, <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a> of <var title="">container</var>).

  <li>
  <p class=comments>We don't want the start to be just inside a node, because
  if it is, we'll leave behind an empty element either in the new or old
  container.  Empty block nodes are fine, and we'll add a <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code> later, but
  empty inline nodes are bad, since the user can't interact with them.

  <p>While <var title="">new line range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is zero and its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is not a <a href=#prohibited-paragraph-child>prohibited paragraph child</a>, set its
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> to (<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>).

  <li>While <var title="">new line range</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-offset title=concept-range-start-offset>start offset</a> is the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>
  of its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> and its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is not a <a href=#prohibited-paragraph-child>prohibited
  paragraph child</a>, set its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a> to (<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>, 1 + <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a>).

  <li>Let <var title="">end of line</var> be true if <var title="">new line range</var>
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained title=contained>contains</a> either nothing or a single <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>, and false otherwise.

  <li>
  <p class=comments>IE9 makes a new header if there's a trailing &lt;br&gt;.
  Firefox 5.0a2, Chrome 13 dev, and Opera 11.10 do not, and I follow them,
  since it makes more sense (such a &lt;br&gt; is invisible).

  <p>If the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> of <var title="">container</var> is "h1", "h2", "h3", "h4",
  "h5", or "h6", and <var title="">end of line</var> is true, let <var title="">new container
  name</var> be the <a href=#default-single-line-container-name>default single-line container name</a>.

  <li>
  <p class=comments>This step and the next follow Firefox 5.0a2.  IE9 and
  Chrome 13 dev act as though these two lines were not present (they clone the
  existing element).  Opera 11.10 nests a &lt;p&gt; inside.  Firefox is the most
  useful, assuming a definition list somehow winds up inside the content (like
  via formatBlock).

  <p>Otherwise, if the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> of <var title="">container</var> is "dt" and
  <var title="">end of line</var> is true, let <var title="">new container name</var> be "dd".

  <li>Otherwise, if the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> of <var title="">container</var> is "dd" and
  <var title="">end of line</var> is true, let <var title="">new container name</var> be "dt".

  <li>Otherwise, let <var title="">new container name</var> be the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-element-local-name title=concept-element-local-name>local name</a> of
  <var title="">container</var>.

  <li>Let <var title="">new container</var> be the result of calling
  <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement(<var title="">new container name</var>)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

  <li>Copy all attributes of <var title="">container</var> to <var title="">new container</var>.

  <li>If <var title="">new container</var> has an <code class=external data-anolis-spec=html title="the id attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-id-attribute>id</a></code> attribute, unset it.

  <li>Insert <var title="">new container</var> into the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> of
  <var title="">container</var> immediately after <var title="">container</var>.

  <li>Let <var title="">contained nodes</var> be all <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new
  line range</var>.

  <li>
  <p class=comments>TODO: This blows up any ranges (other than the selection,
  which we reset), and can alter non-editable nodes, and maybe other bad stuff.
  May or may not be the best solution.  The intermediate fragment is also
  possibly black-box detectable by DOM mutation events, but I like to pretend
  those don't exist.

  <p>Let <var title="">frag</var> be the result of calling <code class=external data-anolis-spec=dom title=dom-Range-extractContents><a href=http://dom.spec.whatwg.org/#dom-range-extractcontents>extractContents()</a></code> on
  <var title="">new line range</var>.

  <li>Unset the <code class=external data-anolis-spec=html title="the id attribute"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-id-attribute>id</a></code> attribute (if any) of each <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#element>Element</a></code> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendant</a> of
  <var title="">frag</var> that is not in <var title="">contained nodes</var>.

  <li>Call <code class=external data-anolis-spec=dom title=dom-Node-appendChild><a href=http://dom.spec.whatwg.org/#dom-node-appendchild>appendChild(<var title="">frag</var>)</a></code> on <var title="">new container</var>.

  <li>
  <p class=comments>Needed in case we have something like
  <code title="">&lt;ol&gt;&lt;li&gt;&lt;p&gt;[]foo&lt;/ol&gt;</code>, which becomes
  <code title="">&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;li&gt;&lt;p&gt;foo&lt;/ol&gt;</code>.  In this case we want to add the <code class=external data-anolis-spec=html title="the br element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-br-element>br</a></code>
  to the <code class=external data-anolis-spec=html title="the p element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-p-element>p</a></code>, not the <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>.  Likewise for <code title="">&lt;ol&gt;&lt;li&gt;&lt;p&gt;foo[]&lt;/ol&gt;</code>.

  <p>While <var title="">container</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> is a <a href=#prohibited-paragraph-child>prohibited paragraph
  child</a>, set <var title="">container</var> to its <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code>.

  <li>While <var title="">new container</var>'s <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code> is a <a href=#prohibited-paragraph-child>prohibited
  paragraph child</a>, set <var title="">new container</var> to its <code class=external data-anolis-spec=dom title=dom-Node-lastChild><a href=http://dom.spec.whatwg.org/#dom-node-lastchild>lastChild</a></code>.

  <li>If <var title="">container</var> has no <a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, call
  <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>, and append the result as the
  last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">container</var>.

  <li>
  <p class=comments>These two steps follow Firefox 5.0a2, Chrome 13 dev, and
  Opera 11.10.  IE9 instead inserts an &amp;nbsp; which magically does not
  appear in innerHTML.  In all cases, the reason is that an empty block box in
  CSS will have zero height, so the user won't be able to put the selection
  cursor inside it.

  <p>If <var title="">new container</var> has no <a href=#visible>visible</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>,
  call <code class=external data-anolis-spec=dom title=dom-Document-createElement><a href=http://dom.spec.whatwg.org/#dom-document-createelement>createElement("br")</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>, and append the result
  as the last <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of <var title="">new container</var>.

  <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">new container</var>, 0)</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li>Return true.
</ol>


<h3 id=the-inserttext-command><dfn>The <code title="">insertText</code> command</dfn></h3>

<div class=note>
<p>This is the same as typing text (see <a href=#additional-requirements>Additional requirements</a>).  If the input
string is more than one character, first we split it up into one execution per
character, for simplicity.  The general rule is then that we record each
command's <a href=#state-override>state override</a> or <a href=#value-override>value override</a>, insert
the new character and select it, restore any overrides that we saved, and
collapse the selection to its end.

<p>The idea of the override business is that the user might run a command like
bold when the selection is collapsed.  There's nothing to bold in that case,
but if the user runs bold and then types a character, they expect it to be
bold.  Thus we save the requested state in an override and restore it when the
user types.  Deleting things can also set overrides, if the deleted text was
styled.

<p>Whitespace is a special case.  The note for <a href=#canonical-space-sequences>canonical space sequences</a> gives some of the
background.  If the user tries typing a space, we make it non-breaking so it
doesn't collapse with anything, then canonicalize whitespace around the
insertion point so line breaking isn't adversely affected.

<p>One last special case is a newline.  For that we just pass off to <a href=#the-insertparagraph-command>the
<code title="">insertParagraph</code> command</a>.
</div>

<div class=comments>
<p>Supported only by WebKit.  Tests in other browsers were manual.

<p>TODO: This doesn't work well if the input contains things that aren't
supposed to appear in HTML, like carriage returns or nulls.  Nor is it going to
work well if the current cursor position is in between two halves of a non-BMP
character.  This will result in unserializability.  The current spec disregards
this, as Chrome 14 dev does.  (It's not relevant to other browsers, since they
don't support this as a command.)

<p>Important issue: non-breaking space fun!  The issue: if the user hits space
twice, they expect it to create two spaces, not collapse.  Also, if they're at
the beginning or end of a line and hit space, again, they expect it not to
collapse.  Since we don't want to require that all contenteditable element
contents always be used only with white-space: pre-wrap, we need to convert to
and from non-breaking spaces.

<p>But there's a catch: you can't just make spaces non-breaking willy-nilly,
because that doesn't just stop the space from collapsing, it also prevents
breaking.  (Chrome 14 dev actually cheats here: in contenteditable, it doesn't
collapse nbsp, but breaks after it like a regular space.)  The upshot of this
is that any nbsp needs to be followed by a space, or else it might end up at
the beginning of a line and be visible there; and it needs to be preceded by a
space, or else it might break a line prematurely.  How to achieve both of these
goals when there are an even number of spaces to display is left as an exercise
for the reader.

<p>Browsers vary greatly in how they handle all this, of course!

<p>The basic philosophy of IE9 is that if you're inserting a space, and one or
both of the neighboring characters is a space, change the neighboring
characters to non-breaking spaces.  This breaks if one of the neighboring
characters is part of a run of collapsed whitespace: "foo  []bar" becomes "foo
&amp;nbsp; []bar", which converts one visible space to three.

<p>Firefox 6.0a2 will sometimes convert the space you're inserting to an nbsp,
sometimes convert neighboring spaces to nbsps, and sometimes convert
neighboring nbsps to spaces.  I cannot discern any clear reason to when it
chooses what, except that it seems to prefer runs of nbsp's followed by a
single space (although not always).  I didn't find any outright bugs, except
the inevitable ones like nbsp's sometimes being right after letters.

<p>Chrome 14 dev tries to normalize everything to look like " &amp;nbsp;
&amp;nbsp; ...", alternating with space then nbsp.  Unfortunately, it does so
buggily, because it converts collapsed spaces to nbsp's, so inserting a space
before " " makes it into " &amp;nbsp; &amp;nbsp;", which changes one visible
space to four (or arbitrarily many).

<p>Opera 11.11 has varying behavior, like Firefox and Chrome.  Like Firefox, I
didn't discern an obvious pattern.

<p>This was all <a href=http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-June/032187.html>discussed</a>.

<p>Unfortunately, we're stuck with this nbsp stuff, because of 1) legacy
reasons, 2) mail clients might not support CSS equivalents, 3) authors might
not know to apply any CSS to wherever the content is eventually used.  The
behavior I decided on to minimize the evil is as follows:

<ul>
  <li>If the first and last spaces are in non-collapsing positions, two spaces
  is nbsp+space, three is space+nbsp+space, four or more is space+nbsp followed
  by the pattern for two less.

  <li>If the first space has to be an nbsp so it doesn't collapse, three is
  instead nbsp+nbsp+space, four or more is nbsp+space followed by the pattern
  for two less.

  <li>If the last space has to be nbsp, two is space+nbsp, three is
  space+nbsp+nbsp, four or more is space+nbsp followed by the pattern for two
  less.

  <li>If the first and last space must both be nbsp, two is nbsp+nbsp, three is
  nbsp+space+nbsp, four or more nbsp+space followed by the pattern for two
  less.
</ul>

<p>This avoids nbsp at the end of a run except where it's needed, so words
won't appear indented if they wrap to the next line.  It avoids more than two
nbsp's in a row, so there won't be huge chunks of space that get wrapped all at
once.  And it avoids nbsp at the beginning of a run except where it's needed or
if there are only two spaces in the run, so words won't have to wrap
unnecessarily.

<p>This is still a huge headache, though.
</div>

<p><a href=#action>Action</a>:

<ol>
  <li>
  <div class=comments>
  <p>Chrome 14 dev does the deletion even if the value is empty.  Of course,
  other browsers don't expose this as an execCommand(), so no one else has any
  defined behavior in this case at all, so I follow Chrome.

  <p>IE9, Firefox 7.0a2, Chrome 14 dev, and Opera 11.50 all don't strip
  wrappers, except that as usual, Gecko does if you select the whole wrapper,
  like {&lt;b&gt;foo&lt;/b&gt;}.  Also, Chrome 14 dev seems to strip the wrapper and
  try recreating the style in cases like &lt;b&gt;[foo&lt;/b&gt;bar], where it starts
  in a wrapper but ends after it; this doesn't always work so well, so I don't
  do it.  Firefox 7.0a2 also has the deletion set overrides for indeterminate
  state commands, so if you run insertText on [foo&lt;b&gt;bar&lt;/b&gt;baz] it will
  make the result bold.

  <p>These things don't make any sense to me, so I don't do them.  I set
  overrides based on the first editable text node in the range when deleting;
  preserve any wrappers at the start of the range; and restore the overrides in
  case preserving the wrappers isn't enough (like if they weren't set by
  deletion at all).  This behavior seems to closely match IE9.
  </div>

  <p><a href=#delete-the-selection>Delete the selection</a>, with <var title="">strip wrappers</var> false.

  <li>If the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> is neither
  <a href=#editable>editable</a> nor an <a href=#editing-host>editing host</a>, return true.

  <li>If <var title="">value</var>'s <a href=http://es5.github.com/#x15.5.5.1>length</a> is greater than one:

  <ol>
    <li>For each <a href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-code-unit>code unit</a> <var title="">el</var> in <var title="">value</var>, take the
    <a href=#action>action</a> for <a href=#the-inserttext-command>the <code title="">insertText</code>
    command</a>, with <var title="">value</var> equal to <var title="">el</var>.

    <li>Return true.
  </ol>

  <li>If <var title="">value</var> is the empty string, return true.

  <li>
  <p class=comments>TODO: WebKit also does magic for tabs, wrapping them in a
  whitespace-preserving span.  Should we?

  <p>If <var title="">value</var> is a newline (U+00A0), take the <a href=#action>action</a>
  for <a href=#the-insertparagraph-command>the <code title="">insertParagraph</code> command</a> and return
  true.

  <li>Let <var title="">node</var> and <var title="">offset</var> be the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start-node title=concept-range-start-node>start node</a> and <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-bp-offset title=concept-range-bp-offset>offset</a>.

  <li>
  <p class=comments>Just to be tidy, add to an existing text node if there is
  one.  Firefox 5.0a2 only adds to an existing one if the range is in a text
  node.  IE9, Chrome 14 dev, and Opera 11.11 also add to an existing text node
  if the range is in an element adjacent to a text node.  If there are two text
  nodes and it's in between, like foo{}bar, IE and Opera add to the first,
  Chrome adds to the second, although it probably doesn't matter in practice
  exactly which we choose.

  <p>If <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> is <var title="">offset</var>
  &minus; 1, and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, set <var title="">node</var> to that
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, then set <var title="">offset</var> to <var title="">node</var>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node-length title=concept-node-length>length</a>.

  <li>If <var title="">node</var> has a <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-index title=concept-tree-index>index</a> is <var title="">offset</var>,
  and that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node, set <var title="">node</var> to that <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>,
  then set <var title="">offset</var> to zero.

  <li><a href=#record-current-overrides>Record current overrides</a>, and let <var title="">overrides</var> be
  the result.

  <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at (<var title="">node</var>,
  <var title="">offset</var>).

  <li>Let (<var title="">node</var>, <var title="">offset</var>) be the <a href=#active-range>active
  range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>.

  <li>If <var title="">node</var> is a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#text>Text</a></code> node:

  <ol>
    <li>Call <code class=external data-anolis-spec=dom title=dom-CharacterData-insertData><a href=http://dom.spec.whatwg.org/#dom-characterdata-insertdata>insertData(<var title="">offset</var>, <var title="">value</var>)</a></code> on
    <var title="">node</var>.

    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">node</var>, <var title="">offset</var>)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">node</var>, <var title="">offset</var> + 1)</a></code> on the
    <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.
  </ol>

  <li>Otherwise:

  <ol>
    <li>
    <p class=comments>If some text is inserted into &lt;p&gt;&lt;br&gt;&lt;/p&gt; or
    similar, we no longer need the &lt;br&gt;.

    <p>If <var title="">node</var> has only one <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a>, which is a <a href=#collapsed-line-break>collapsed
    line break</a>, remove its <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> from it.

    <li>Let <var title="">text</var> be the result of calling
    <code class=external data-anolis-spec=dom title=dom-Document-createTextNode><a href=http://dom.spec.whatwg.org/#dom-document-createtextnode>createTextNode(<var title="">value</var>)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

    <li>Call <code class=external data-anolis-spec=dom title=dom-Range-insertNode><a href=http://dom.spec.whatwg.org/#dom-range-insertnode>insertNode(<var title="">text</var>)</a></code> on the <a href=#active-range>active range</a>.

    <li>Call <code title=dom-Selection-collapse><a href=#dom-selection-collapse>collapse(<var title="">text</var>, 0)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
    <a href=#concept-selection title=concept-selection>selection</a>.

    <li>Call <code title=dom-Selection-extend><a href=#dom-selection-extend>extend(<var title="">text</var>, 1)</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
    <a href=#concept-selection title=concept-selection>selection</a>.
  </ol>

  <li><a href=#restore-states-and-values>Restore states and values</a> from <var title="">overrides</var>.

  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>, with <var title="">fix collapsed space</var> false.

  <li><a href=#canonicalize-whitespace>Canonicalize whitespace</a> at the <a href=#active-range>active range</a>'s
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a>, with <var title="">fix collapsed space</var> false.

  <li>If <var title="">value</var> is a <a class=external data-anolis-spec=encoding href=http://encoding.spec.whatwg.org/#ascii-whitespace title="ascii whitespace">space character</a>, <a href=#autolink>autolink</a> the
  <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>.

  <li>Call <code title=dom-Selection-collapseToEnd><a href=#dom-selection-collapsetoend>collapseToEnd()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <a href=#concept-selection title=concept-selection>selection</a>.

  <li>Return true.
</ol>


<h3 id=the-insertunorderedlist-command><dfn>The <code title="">insertUnorderedList</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p class=comments>See comments for <a href=#the-insertorderedlist-command>insertOrderedList</a>.

<p><a href=#action>Action</a>: <a href=#toggle-lists>Toggle lists</a> with <var title="">tag name</var>
"ul", then return true.

<p><a href=#indeterminate>Indeterminate</a>: True if the <a href="#selection's-list-state">selection's list state</a>
is "mixed" or "mixed ul", false otherwise.

<p><a href=#state>State</a>: True if the <a href="#selection's-list-state">selection's list state</a> is "ul",
false otherwise.


<h3 id=the-justifycenter-command><dfn>The <code title="">justifyCenter</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
<var title="">alignment</var> "center", then return true.

<div class=comments>
<p>This roughly matches Chrome 14 dev, although not exactly.  Firefox 6.0a2
always returns false.

<p>As a general rule, ignoring nodes with children saves us from treating
&lt;div align=left&gt;&lt;div align=center&gt;foo&lt;/div&gt;&lt;/div&gt; as though it's
indeterminate.  Chrome 14 dev seems to only pay attention to text nodes,
instead, or something like that.  At any rate, it fails on images.  Firefox
6.0a2 (for state and value) gets tripped up by examples like the one given.

<p>If we ever support centering of tables and similar, we'd want to pay
attention even to some nodes that do have children.
</div>

<p><a href=#indeterminate>Indeterminate</a>: Return false if the <a href=#active-range>active range</a> is
null.  Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>.
Return true if among <a href=#visible>visible</a> <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> that
are <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and have no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, at least one has
<a href=#alignment-value>alignment value</a> "center" and at least one does not.  Otherwise
return false.

<div class=comments>
<p>IE9 throws exceptions in almost every case when querying the state of
justify*, and Opera 11.11 returns false in every case except some seemingly
random crazy ones.

<p>Firefox 6.0a2 returns true for the state of justify* if anything in the
range has the right alignment, not if everything does.  This isn't consistent
with how state works for the inline commands, nor with WebKit.

<p>Chrome 14 dev counts text-align on inline elements, which is wrong, because
the property has no effect.  It also counts it on non-editable elements, which
is wrong, because then the state for justify* wouldn't necessarily be true
after executing it.  (Chrome actually does align the non-editable elements, but
that's just a bug.)  Chrome further returns false for justify* if the
justification is just the default inherited justification, e.g., left for LTR.
This doesn't seem to make sense either.

<p>State is kind of redundant here, because it's true if and only if
indeterminate is false and the value is equal to the desired value.  However,
I'll support it anyway, since Gecko/WebKit do.
</div>

<p><a href=#state>State</a>: Return false if the <a href=#active-range>active range</a> is null.
Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>.  Return
true if there is at least one <a href=#visible>visible</a> <a href=#editable>editable</a>
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, and all
such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> have <a href=#alignment-value>alignment value</a> "center".  Otherwise return
false.

<p class=comments>Not bidi-safe, but it's a pretty marginal corner case where
it fails.  Firefox 6.0a2 behaves weirdly here: it keys off the start node of
the active range, even if that's not contained.  Thus {&lt;div
align=center&gt;foo&lt;/div&gt;} has value "left" and indeterminate false, which
would suggest that the whole selection is aligned left, but that's not the
case.  Chrome 14 dev returns the state cast to a string, as usual.  Opera 11.11
always returns the empty string.

<p><a href=#value>Value</a>: Return the empty string if the <a href=#active-range>active range</a>
is null.  Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>,
and return the <a href=#alignment-value>alignment value</a> of the first <a href=#visible>visible</a>
<a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and has no
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>.  If there is no such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, return "left".


<h3 id=the-justifyfull-command><dfn>The <code title="">justifyFull</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
<var title="">alignment</var> "justify", then return true.

<p><a href=#indeterminate>Indeterminate</a>: Return false if the <a href=#active-range>active range</a> is
null.  Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>.
Return true if among <a href=#visible>visible</a> <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> that
are <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and have no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, at least one has
<a href=#alignment-value>alignment value</a> "justify" and at least one does not.  Otherwise
return false.

<p><a href=#state>State</a>: Return false if the <a href=#active-range>active range</a> is null.
Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>.  Return
true if there is at least one <a href=#visible>visible</a> <a href=#editable>editable</a>
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, and all
such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> have <a href=#alignment-value>alignment value</a> "justify".  Otherwise return
false.

<p><a href=#value>Value</a>: Return the empty string if the <a href=#active-range>active range</a>
is null.  Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>,
and return the <a href=#alignment-value>alignment value</a> of the first <a href=#visible>visible</a>
<a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and has no
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>.  If there is no such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, return "left".


<h3 id=the-justifyleft-command><dfn>The <code title="">justifyLeft</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
<var title="">alignment</var> "left", then return true.

<p><a href=#indeterminate>Indeterminate</a>: Return false if the <a href=#active-range>active range</a> is
null.  Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>.
Return true if among <a href=#visible>visible</a> <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> that
are <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and have no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, at least one has
<a href=#alignment-value>alignment value</a> "left" and at least one does not.  Otherwise
return false.

<p><a href=#state>State</a>: Return false if the <a href=#active-range>active range</a> is null.
Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>.  Return
true if there is at least one <a href=#visible>visible</a> <a href=#editable>editable</a>
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, and all
such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> have <a href=#alignment-value>alignment value</a> "left".  Otherwise return
false.

<p><a href=#value>Value</a>: Return the empty string if the <a href=#active-range>active range</a>
is null.  Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>,
and return the <a href=#alignment-value>alignment value</a> of the first <a href=#visible>visible</a>
<a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and has no
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>.  If there is no such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, return "left".


<h3 id=the-justifyright-command><dfn>The <code title="">justifyRight</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>: <a href=#justify-the-selection>Justify the selection</a> with
<var title="">alignment</var> "right", then return true.

<p><a href=#indeterminate>Indeterminate</a>: Return false if the <a href=#active-range>active range</a> is
null.  Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>.
Return true if among <a href=#visible>visible</a> <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> that
are <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and have no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, at least one has
<a href=#alignment-value>alignment value</a> "right" and at least one does not.  Otherwise
return false.

<p><a href=#state>State</a>: Return false if the <a href=#active-range>active range</a> is null.
Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>.  Return
true if there is at least one <a href=#visible>visible</a> <a href=#editable>editable</a>
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and has no <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>, and all
such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a> have <a href=#alignment-value>alignment value</a> "right".  Otherwise return
false.

<p><a href=#value>Value</a>: Return the empty string if the <a href=#active-range>active range</a>
is null.  Otherwise, <a href=#block-extend>block-extend</a> the <a href=#active-range>active range</a>,
and return the <a href=#alignment-value>alignment value</a> of the first <a href=#visible>visible</a>
<a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> that is <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in the result and has no
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>children</a>.  If there is no such <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, return "left".


<h3 id=the-outdent-command><dfn>The <code title="">outdent</code> command</dfn></h3>

<p><a href=#preserves-overrides>Preserves overrides</a>

<p><a href=#action>Action</a>:

<ol>
  <li>Let <var title="">items</var> be a list of all <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code>s that are
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor title=concept-tree-inclusive-ancestor>inclusive ancestors</a> of the <a href=#active-range>active range</a>'s <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-start title=concept-range-start>start</a>
  and/or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-range-end title=concept-range-end>end</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>.

  <li>
  <p class=comments>TODO: This overnormalizes, but it seems like the simplest
  solution for now.

  <p>For each <var title="">item</var> in <var title="">items</var>, <a href=#normalize-sublists>normalize
  sublists</a> of <var title="">item</var>.

  <li><a href=#block-extend>Block-extend</a> the <a href=#active-range>active range</a>, and let <var title="">new
  range</var> be the result.

  <li>Let <var title="">node list</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

  <li>
  <div class=comments>
  <p>This step is kind of weird.  For regular outdenting, we start at the
  inside and outdent going out, so that we remove the innermost indentation, on
  the theory that that will produce the cleanest markup (remove the most
  nodes).  For lists, we remove the outermost indentation, because it makes a
  difference whether we remove inner or outer indentation, and logically we
  want to remove outer.  E.g.,

    <pre>&lt;ol&gt;&lt;li&gt;foo&lt;/li&gt;&lt;ul&gt;&lt;li&gt;bar&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;</pre>

  <p>should become

    <pre>foo&lt;ul&gt;&lt;li&gt;bar&lt;/li&gt;&lt;/ul&gt;</pre>

  <p>not

    <pre>foo&lt;ol&gt;&lt;li&gt;bar&lt;/li&gt;&lt;/ol&gt;.</pre>

  <p>But this is a bit weird and I'm wondering if it's really correct.  TODO:
  Reexamine this.
  </div>

  <p>For each <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a> <var title="">node</var> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#contained>contained</a> in <var title="">new range</var>,
  append <var title="">node</var> to <var title="">node list</var> if the last member of
  <var title="">node list</var> (if any) is not an <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-ancestor title=concept-tree-ancestor>ancestor</a> of <var title="">node</var>;
  <var title="">node</var> is <a href=#editable>editable</a>; and either <var title="">node</var> has no
  <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-descendant title=concept-tree-descendant>descendants</a>, or is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, or is an
  <code class=external data-anolis-spec=html title="the li element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element>li</a></code> whose <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-parent title=concept-tree-parent>parent</a> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>.

  <li>While <var title="">node list</var> is not empty:

  <ol>
    <li>While the first member of <var title="">node list</var> is an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>
    or is not the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-tree-child title=concept-tree-child>child</a> of an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, <a href=#outdent>outdent</a> it and
    remove it from <var title="">node list</var>.

    <li>If <var title="">node list</var> is empty, break from these substeps.

    <li>Let <var title="">sublist</var> be a list of <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>nodes</a>, initially empty.

    <li>Remove the first member of <var title="">node list</var> and append it to
    <var title="">sublist</var>.

    <li>While the first member of <var title="">node list</var> is the <code class=external data-anolis-spec=dom title=dom-Node-nextSibling><a href=http://dom.spec.whatwg.org/#dom-node-nextsibling>nextSibling</a></code>
    of the last member of <var title="">sublist</var>, and the first member of <var title="">node
    list</var> is not an <code class=external data-anolis-spec=html title="the ol element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ol-element>ol</a></code> or <code class=external data-anolis-spec=html title="the ul element"><a href=http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-ul-element>ul</a></code>, remove the first member of <var title="">node
    list</var> and append it to <var title="">sublist</var>.

    <li><a href=#record-the-values>Record the values</a> of <var title="">sublist</var>, and let
    <var title="">values</var> be the result.

    <li><a href=#split-the-parent>Split the parent</a> of <var title="">sublist</var>.

    <li><a href=#fix-disallowed-ancestors>Fix disallowed ancestors</a> of each member of
    <var title="">sublist</var>.

    <li><a href=#restore-the-values>Restore the values</a> from <var title="">values</var>.
  </ol>

  <li>Return true.
</ol>


<h2 id=miscellaneous-commands>Miscellaneous commands</h2>

<h3 id=the-copy-command><dfn>The <code title="">copy</code> command</dfn></h3>

<p class=comments>IE9 supports copy/cut/paste with a security warning.  Firefox
reportedly only supports it if you set a pref.  I didn't find info on other
browsers, but in my tests it didn't do anything.  I'm not going to try speccing
it unless implementers are interested in working out the security problems and
trying to get interop.  It seems like as of June 2011, everyone just <a href=http://code.google.com/p/zeroclipboard/>uses Flash for this</a>.  So it
would be nice if we could work out a more secure standardized substitute.

<p><a href=#action>Action</a>: The user agent must either copy the current selection
to the clipboard as though the user had requested it, or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> a
<code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#securityerror>SecurityError</a></code> exception.  This specification does not define exactly how the
selection is to be copied to the clipboard, but the <a href=http://dev.w3.org/2006/webapi/clipops/clipops.html>Clipboard API and
events</a> specification might be useful.

<p>User agents should exercise caution in respecting this <a href=#command>command</a>,
because sites could abuse it to confuse and annoy the user by overwriting the
clipboard with extremely long, obscene, or otherwise objectionable content.

<p class=comments>The idea is sites might catch the SECURITY_ERR and treat it
differently from NOT_SUPPORTED_ERR, like encouraging users to reconfigure their
browser.  However, browsers might not want to encourage authors to tell users
to reconfigure their browser insecurely.

<p>User agents may choose not to <a href=#supported title=supported>support</a> this
<a href=#command>command</a> at all.  If a user agent will only honor the
<a href=#command>command</a> for some whitelisted sites depending on configuration, it
may either <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#securityerror>SecurityError</a></code> exception for non-whitelisted sites,
or it may act as though the <a href=#command>command</a> is <a href=#supported title=supported>unsupported</a> on those sites.


<h3 id=the-cut-command><dfn>The <code title="">cut</code> command</dfn></h3>

<p class=comments>See comment for <a href=#the-copy-command>copy</a>.

<p><a href=#action>Action</a>: The user agent must either copy the current selection
to the clipboard and then delete it, as though the user had requested it, or
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#securityerror>SecurityError</a></code> exception.  This specification does not define
exactly how the selection is to be deleted or copied to the clipboard, but the
<a href=http://dev.w3.org/2006/webapi/clipops/clipops.html>Clipboard API and
events</a> specification might be useful.

<p>User agents should exercise caution in respecting this command, because
sites could abuse it to confuse and annoy the user by overwriting the clipboard
with extremely long, obscene, or otherwise objectionable content.

<p>User agents may choose not to <a href=#supported title=supported>support</a> this
<a href=#command>command</a> at all.  If a user agent will only honor the
<a href=#command>command</a> for some whitelisted sites depending on configuration, it
may either <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#securityerror>SecurityError</a></code> exception for non-whitelisted sites,
or it may act as though the <a href=#command>command</a> is <a href=#supported title=supported>unsupported</a> on those sites.


<h3 id=the-defaultparagraphseparator-command><dfn>The <code title="">defaultParagraphSeparator</code> command</dfn></h3>

<p class=XXX>This is a new feature, added by request in
<a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=15527">bug 15527</a>.
(Opera already had an o-defaultblock command that worked similarly.)
<strong>If you are implementing this, please make sure to file any feedback as
bugs. The spec is not finalized yet and can still be easily changed.</strong>

<p><a href=#action>Action</a>: Let <var title="">value</var> be
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#converted-to-ascii-lowercase>converted to ASCII lowercase</a>.  If
<var title="">value</var> is then equal to "p" or "div", set the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
<a href=#default-single-line-container-name>default single-line container name</a> to <var title="">value</var>, then
return true.  Otherwise, return false.

<p><a href=#value>Value</a>: Return the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s
<a href=#default-single-line-container-name>default single-line container name</a>.


<h3 id=the-paste-command><dfn>The <code title="">paste</code> command</dfn></h3>

<p class=comments>See comment for <a href=#the-copy-command>copy</a>.

<p><a href=#action>Action</a>: The user agent must either <a href=#delete-the-selection>delete the
selection</a> and then paste the clipboard's contents to the current cursor
position, as though the user had requested it, or <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#securityerror>SecurityError</a></code>
exception.  This specification does not define exactly how the clipboard is to
be converted to HTML for pasting, but the <a href=http://dev.w3.org/2006/webapi/clipops/clipops.html>Clipboard API and
events</a> specification might be useful.

<p>User agents should exercise caution in respecting this command,
because sites could abuse it to read private information from the clipboard.

<p>User agents may choose not to <a href=#supported title=supported>support</a> this
<a href=#command>command</a> at all.  If a user agent will only honor the
<a href=#command>command</a> for some whitelisted sites depending on configuration, it
may either <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-throw title=concept-throw>throw</a> a <code class=external data-anolis-spec=dom><a href=http://dom.spec.whatwg.org/#securityerror>SecurityError</a></code> exception for non-whitelisted sites,
or it may act as though the <a href=#command>command</a> is <a href=#supported title=supported>unsupported</a> on those sites.


<h3 id=the-redo-command><dfn>The <code title="">redo</code> command</dfn></h3>

<p><a href=#action>Action</a>: As defined by the <a href=http://rniwa.com/editing/undomanager.html>UndoManager</a> specification.


<h3 id=the-selectall-command><dfn>The <code title="">selectAll</code> command</dfn></h3>

<p class=XXX>This is totally broken: if executed inside an editing host, it has
to select the editing host contents, not the whole document.  See <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13840">bug</a>.

<div class=comments>
<p>Tested using roughly <a href=http://software.hixie.ch/utilities/js/live-dom-viewer/saved/1018>this</a>.

<dl>
  <dt>IE9
  <dd>A bit confusing.  The gist seems to be that it does selectAllChildren()
  on the body, except sometimes it doesn't.

  <dt>Firefox 5.0a2
  <dd>Throws an exception if nothing in the document is editable, which
  apparently it always does for execCommand().  If there's a body, it does
  selectAllChildren() on that, and otherwise it does selectAllChildren() on the
  root element.  If there's no root element, throws an exception.

  <dt>Chrome 13 dev
  <dd>If there's no root element, removes the selection.  If there's a root
  element but no body, collapses the selection at (document, 0).  If there's a
  body, it selects all the contents of the body, although that doesn't mean the
  resulting anchor or focus actually are the body node (they're usually text
  nodes).  But it seems to *avoid* selecting contenteditable stuff: if all the
  visible things in the body are contenteditable, it removes all ranges from
  the selection, and if some are, it freaks out and behaves oddly.  But
  designMode doesn't trouble it.

  <dt>Opera 11.11
  <dd>Was characteristically uncooperative in my tests, and I didn't try to
  investigate further.
</dl>

<p>The behavior here is relatively simple and largely matches implementations.
</div>

<p><a href=#action>Action</a>:

<ol>
  <li>
  <p class=comments>TODO: Is this right even for framesets?

  <p>Let <var title="">target</var> be <a class=external data-anolis-spec=html href=http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#the-body-element-0 title=the-body-element-0>the body element</a> of the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>.

  <p class=comments>TODO: Is this right even for documents whose root element
  is not an HTML element?

  <p>If <var title="">target</var> is null, let <var title="">target</var> be the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>'s <code class=external data-anolis-spec=domcore title=dom-Document-documentElement><a href=http://dom.spec.whatwg.org/#dom-document-documentelement>documentElement</a></code>.

  <li>If <var title="">target</var> is null, call <code title=dom-Document-getSelection><a href=#dom-document-getselection>getSelection()</a></code> on the
  <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>, and call <code title=dom-Selection-removeAllRanges><a href=#dom-selection-removeallranges>removeAllRanges()</a></code> on the result.

  <li>Otherwise, call <code title=dom-Document-getSelection><a href=#dom-document-getselection>getSelection()</a></code> on the <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#context-object>context object</a>, and call
  <code title=dom-Selection-selectAllChildren><a href=#dom-selection-selectallchildren>selectAllChildren(<var title="">target</var>)</a></code> on the result.

  <li>Return true.
</ol>


<h3 id=the-stylewithcss-command><dfn>The <code title="">styleWithCSS</code> command</dfn></h3>

<div class=comments>
<p>IE9 and Opera 11.00 don't support this command.  By and large, they act the
way Gecko and WebKit do when styleWithCSS is off.  Gecko invented it, and
WebKit also <a href="https://bugs.webkit.org/show_bug.cgi?id=13490">supports</a>
it.  The default in Firefox 4.0 is off, while all other browsers behave like
the default is on (and IE/Opera give no way to turn it off), so I default it to
on.

<p>Handling of <var title="">value</var> matches Firefox 5.0a2.  Chrome 13 dev treats
the case-sensitive string "true" as true, the case-sensitive string "false" as
false, and does nothing for any other string.  I went with Gecko because this
way there are only two possible effects, not three, which makes it easier to
reason about and debug.  Also, Gecko made up the command, so this is probably
more web-compatible.  Cursory searches of Google Code and GitHub suggest that
authors almost always pass a boolean as the third argument when using
styleWithCSS, in which case the two behaviors work the same.
</div>

<p><a href=#action>Action</a>: If <var title="">value</var> is an <a class=external data-anolis-spec=domcore href=http://dom.spec.whatwg.org/#ascii-case-insensitive>ASCII case-insensitive</a> match for the string
"false", set the <a href=#css-styling-flag>CSS styling flag</a> to false.  Otherwise, set the
<a href=#css-styling-flag>CSS styling flag</a> to true.  Either way, return true.

<p class=comments>This follows Chrome 13 dev.  Firefox 5.0a2 doesn't support
queryCommandState() for styleWithCSS.

<p><a href=#state>State</a>: True if the <a href=#css-styling-flag>CSS styling flag</a> is true,
otherwise false.


<h3 id=the-undo-command><dfn>The <code title="">undo</code> command</dfn></h3>

<p><a href=#action>Action</a>: As defined by the <a href=http://rniwa.com/editing/undomanager.html>UndoManager</a> specification.


<h3 id=the-usecss-command><dfn>The <code title="">useCSS</code> command</dfn></h3>

<div class=comments>
<p>Supported by Firefox 4.0, but not IE9 or Opera 11.00 (which don't support
styleWithCSS either), nor by Chrome 12 dev (which does support styleWithCSS).
useCSS was the original feature in Mozilla 1.3, but the meaning is backward, so
Gecko added styleWithCSS as a replacement.  No state is defined, since only
Gecko supports useCSS at all, and as of Firefox 6.0a2, it doesn't support
queryCommandState() for it.

<p>As of September 2011, WebKit is <a href="https://bugs.webkit.org/show_bug.cgi?id=36683">adding support</a> for this
command, so it can no longer be considered deprecated.
</div>

<p><a href=#action>Action</a>: If <var title="">value</var> is an <a class=external data-anolis-spec=domcore href=http://dom.spec.whatwg.org/#ascii-case-insensitive>ASCII case-insensitive</a> match for the string
"false", set the <a href=#css-styling-flag>CSS styling flag</a> to true.  Otherwise, set the
<a href=#css-styling-flag>CSS styling flag</a> to false.  Either way, return true.

<p>Since the effect of this command is the opposite of what one would expect,
user agents are encouraged to point authors to <code title="the stylewithcss
command"><a href=#the-stylewithcss-command>styleWithCSS</a></code> when <code title="the usecss
command"><a href=#the-usecss-command>useCSS</a></code> is used, such as by logging a warning to an error
console.

<p class=note>No <a href=#state>state</a> is defined for this command, so <code title=queryCommandState()><a href=#querycommandstate()>queryCommandState("useCSS")</a></code> must always return
false.  To query the <a href=#css-styling-flag>CSS styling flag</a>'s current value, authors
have to use <a href=#the-stylewithcss-command>the <code title="">styleWithCSS</code> command</a>.


<h2 id=additional-requirements>Additional requirements</h2>

<p class=XXX>It has been <a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-December/024628.html>suggested</a>
that some things here need to be platform-dependent, not fully standardized.
For now I'm standardizing them anyway, because the large majority of behavior
should be platform-agnostic.  If anyone has suggestions as to particular things
that should be left up to platform behavior, please say so.

<p>When the user instructs the user agent to insert a line break inside an
<a href=#editing-host>editing host</a>, such as by pressing the Enter key while the cursor
is in an <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, the user agent must call
<code title=execCommand()><a href=#execcommand()>execCommand("insertparagraph")</a></code> on the relevant
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>.

<p>When the user instructs the user agent to insert a line break inside an
<a href=#editing-host>editing host</a> without breaking out of the current block, such as by
pressing Shift-Enter or Option-Enter while the cursor is in an
<a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, the user agent must call
<code title=execCommand()><a href=#execcommand()>execCommand("insertlinebreak")</a></code> on the relevant
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>.

<p>When the user instructs the user agent to delete the previous character
inside an <a href=#editing-host>editing host</a>, such as by pressing the Backspace key
while the cursor is in an <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, the user agent must
call <code title=execCommand()><a href=#execcommand()>execCommand("delete")</a></code> on the relevant
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>.

<p>When the user instructs the user agent to delete the next character inside
an <a href=#editing-host>editing host</a>, such as by pressing the Delete key while the
cursor is in an <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, the user agent must call
<code title=execCommand()><a href=#execcommand()>execCommand("forwarddelete")</a></code> on the relevant
<a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>.

<p>When the user instructs the user agent to insert text inside an
<a href=#editing-host>editing host</a>, such as by typing on the keyboard while the cursor
is in an <a href=#editable>editable</a> <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-node title=concept-node>node</a>, the user agent must call
<code title=execCommand()><a href=#execcommand()>execCommand("inserttext", false, <var title="">value</var>)</a></code>
on the relevant <a class=external data-anolis-spec=dom href=http://dom.spec.whatwg.org/#concept-document title=concept-document>document</a>, with <var title="">value</var> equal to the text the user
provided.  If the user inserts multiple characters at once or in quick
succession, this specification does not define whether it is treated as one
insertion or several consecutive insertions.

<p class=comments><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=13938">Bug 13938</a>.

<p>The user agent may allow the user to make other changes to editable content,
such as causing Ctrl-B to call
<code title=execCommand()><a href=#execcommand()>execCommand("bold")</a></code>.  Any such change must
be accomplished by calling <code><a href=#execcommand()>execCommand()</a></code>, so that in particular,
"beforeinput" and "input" events fire as appropriate.  The <a href=#command>command</a>
invoked should be one of the standard <a href=#command title=command>commands</a>
defined in this specification if possible, and otherwise must be a
<a href=#vendor-specific-command>vendor-specific command</a>.


<h2 class=no-num id=acknowledgements>Acknowledgements</h2>

<p><i title="">This section is not <a href=#normative>normative</a>.</i>

<p>Thanks to:

<ul>
  <li>Google and Mozilla, for funding this work
  <li>Ian Hickson, for overseeing it initially
  <li>Ian Hickson and Ms2ger, for starting the selection work
  <li>Julie Parent, Ojan Vafai, Alex Russel, and Eric Seidel for their <a href=http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-December/024627.html>research</a>
  on how browsers and other rich text editors behave in many common scenarios
  <li>
  Ehsan Akhgari,
  Tab Atkins,
  Mathias Bynens,
  Tim Down,
  Markus Ernst,
  Daniel Glazman,
  Tali Gregor (n&eacute;e Fuss),
  Stig Halvorsen,
  Jeff Harris,
  Ian Hickson,
  Cameron Heavon-Jones,
  Anne van Kesteren,
  Alfonso Mart&iacute;nez de Lizarrondo,
  Glenn Maynard,
  Ms2ger,
  Ryosuke Niwa,
  Robert O'Callahan,
  Julie Parent,
  Simon Pieters,
  Michael A. Puls II,
  Rich Schwerdtfeger,
  Jonas Sicking,
  Henri Sivonen,
  Smylers,
  Hallvord R. M. Steen,
  Roland Steiner,
  Annie Sullivan,
  timeless,
  Ojan Vafai,
  Brett Zamir,
  and
  Boris Zbarsky
  for their feedback, participation, or other helpful contributions
</ul>

<script>

[].forEach.call(document.querySelectorAll(".comments"), function(node) {
  var button = document.createElement("button");
  button.textContent = "View comments";
  button.onclick = function() {
    node.className = node.className == "comments" ? "comments-expanded" : "comments";
  };

  var wrapper = document.createElement("div");
  wrapper.className = "comments-wrapper";
  node.parentNode.insertBefore(wrapper, node);

  wrapper.appendChild(button);
  wrapper.appendChild(node);
});
document.body.onclick = function(e) {
  [].forEach.call(document.querySelectorAll(".comments-expanded"), function(node) {
    if (e.target != node.parentNode
    && !(e.target.compareDocumentPosition(node.parentNode) & Node.DOCUMENT_POSITION_CONTAINS)) {
      node.className = "comments";
    }
  });
};

</script>
<script src=https://www.whatwg.org/specs/web-apps/current-work/dfn.js></script>
